Skip to content

Commit

Permalink
Make getindex for String check if all indices are valid
Browse files Browse the repository at this point in the history
Closes #22548

fixes a bug with use of prevind in dates/io.jl
  • Loading branch information
bkamins authored and vtjnash committed Sep 19, 2017
1 parent e34dba1 commit ed2d32f
Show file tree
Hide file tree
Showing 6 changed files with 18 additions and 9 deletions.
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ Breaking changes

This section lists changes that do not have deprecation warnings.

* `getindex(s::String, r::UnitRange{Int})` now throws `UnicodeError` if `last(r)`
is not a valid index into `s` ([#22572]).

* `ntuple(f, n::Integer)` throws `ArgumentError` if `n` is negative.
Previously an empty tuple was returned ([#21697]).

Expand Down
2 changes: 1 addition & 1 deletion base/dates/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ function DateFormat(f::AbstractString, locale::DateLocale=ENGLISH)

letters = String(collect(keys(CONVERSION_SPECIFIERS)))
for m in eachmatch(Regex("(?<!\\\\)([\\Q$letters\\E])\\1*"), f)
tran = replace(f[prev_offset:m.offset - 1], r"\\(.)", s"\1")
tran = replace(f[prev_offset:prevind(f, m.offset)], r"\\(.)", s"\1")

if !isempty(prev)
letter, width = prev
Expand Down
2 changes: 1 addition & 1 deletion base/repl/LineEdit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ function refresh_multi_line(termbuf::TerminalBuffer, terminal::UnixTerminal, buf
# in this case, we haven't yet written the cursor position
line_pos -= slength # '\n' gets an extra pos
if line_pos < 0 || !moreinput
num_chars = (line_pos >= 0 ? llength : strwidth(l[1:(line_pos + slength)]))
num_chars = (line_pos >= 0 ? llength : strwidth(l[1:prevind(l, line_pos + slength + 1)]))
curs_row, curs_pos = divrem(lindent + num_chars - 1, cols)
curs_row += cur_row
curs_pos += 1
Expand Down
2 changes: 1 addition & 1 deletion base/repl/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,7 @@ function setup_interface(
end
# Check if input line starts with "julia> ", remove it if we are in prompt paste mode
jl_prompt_len = 7
if (firstline || isprompt_paste) && (oldpos + jl_prompt_len <= sizeof(input) && input[oldpos:oldpos+jl_prompt_len-1] == JULIA_PROMPT)
if (firstline || isprompt_paste) && startswith(SubString(input, oldpos), JULIA_PROMPT)
isprompt_paste = true
oldpos += jl_prompt_len
# If we are prompt pasting and current statement does not begin with julia> , skip to next line
Expand Down
13 changes: 9 additions & 4 deletions base/strings/string.jl
Original file line number Diff line number Diff line change
Expand Up @@ -235,20 +235,25 @@ isvalid(s::String, i::Integer) =

function getindex(s::String, r::UnitRange{Int})
isempty(r) && return ""
i, j = first(r), last(r)
l = sizeof(s)
i = first(r)
if i < 1 || i > l
throw(BoundsError(s, i))
end
@inbounds si = codeunit(s, i)
if is_valid_continuation(si)
throw(UnicodeError(UTF_ERR_INVALID_INDEX, i, si))
end
j = last(r)
if j > l
throw(BoundsError())
throw(BoundsError(s, j))
end
j = nextind(s,j)-1
unsafe_string(pointer(s,i), j-i+1)
@inbounds sj = codeunit(s, j)
if is_valid_continuation(sj)
throw(UnicodeError(UTF_ERR_INVALID_INDEX, j, sj))
end
j = nextind(s,j)
unsafe_string(pointer(s,i), j-i)
end

function search(s::String, c::Char, i::Integer = 1)
Expand Down
5 changes: 3 additions & 2 deletions test/strings/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,10 @@ end
@test first('\x00':'\x7f') === '\x00'
@test last('\x00':'\x7f') === '\x7f'

# make sure substrings handle last code unit even if not start of codepoint
# make sure substrings do not accept code unit if it is not start of codepoint
let s = "x\u0302"
@test s[1:3] == s
@test_throws UnicodeError s[1:3]
@test s[1:2]==s
end

# issue #9781
Expand Down

0 comments on commit ed2d32f

Please sign in to comment.