Skip to content

Commit

Permalink
Make resize! a no-op when size does not change
Browse files Browse the repository at this point in the history
Else we set the last element to zero for one-byte element types like UInt8,
which means that resizing a vector allocated with StringVector corrupts it.
Also add redundant checks in Julia code to avoid a function call.
  • Loading branch information
nalimilan committed Feb 17, 2018
1 parent 8ac4d92 commit 851a892
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 1 deletion.
2 changes: 1 addition & 1 deletion base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,7 @@ function resize!(a::Vector, nl::Integer)
l = length(a)
if nl > l
ccall(:jl_array_grow_end, Cvoid, (Any, UInt), a, nl-l)
else
elseif nl != l
if nl < 0
throw(ArgumentError("new length must be ≥ 0"))
end
Expand Down
4 changes: 4 additions & 0 deletions src/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,8 @@ JL_DLLEXPORT void jl_array_del_beg(jl_array_t *a, size_t dec)
jl_bounds_error_int((jl_value_t*)a, dec);
if (__unlikely(a->flags.isshared))
array_try_unshare(a);
if (dec == 0)
return;
jl_array_del_at_beg(a, 0, dec, n);
}

Expand All @@ -1009,6 +1011,8 @@ JL_DLLEXPORT void jl_array_del_end(jl_array_t *a, size_t dec)
jl_bounds_error_int((jl_value_t*)a, 0);
if (__unlikely(a->flags.isshared))
array_try_unshare(a);
if (dec == 0)
return;
jl_array_del_at_end(a, n - dec, dec, n);
}

Expand Down
15 changes: 15 additions & 0 deletions test/arrayops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2342,4 +2342,19 @@ Base.view(::T25958, args...) = args
@test t[end,1,end] == @view(t[end,1,end]) == @views t[end,1,end]
@test t[end,end,1] == @view(t[end,end,1]) == @views t[end,end,1]
@test t[end,end,end] == @view(t[end,end,end]) == @views t[end,end,end]
end

# resize! sets the last element to zero when element size is one byte
@testset "check that resize! is a no-op when size does not change" for T in (Int, UInt8, Int8)
x = Vector{T}(uninitialized, 1)
resize!(x, 0)
unsafe_store!(pointer(x), 1, 1)
resize!(x, 0)
@test unsafe_load(pointer(x), 1) == 1

x = Vector{T}(uninitialized, 2)
resize!(x, 1)
unsafe_store!(pointer(x), 1, 2)
resize!(x, 1)
@test unsafe_load(pointer(x), 2) == 1
end
10 changes: 10 additions & 0 deletions test/strings/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ using Random
@test String("abc!") == "abc!"
@test String(0x61:0x63) == "abc"

# Check that resizing empty source vector does not corrupt string
b = IOBuffer()
write(b, "ab")
x = take!(b)
s = String(x)
resize!(x, 0)
@test s == "ab"
resize!(x, 1)
@test s == "ab"

@test isempty(string())
@test eltype(GenericString) == Char
@test firstindex("abc") == 1
Expand Down

0 comments on commit 851a892

Please sign in to comment.