Skip to content

Commit de014c9

Browse files
committed
Make resize! a no-op when size does not change
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.
1 parent 55ae65b commit de014c9

File tree

4 files changed

+30
-1
lines changed

4 files changed

+30
-1
lines changed

base/array.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -936,7 +936,7 @@ function resize!(a::Vector, nl::Integer)
936936
l = length(a)
937937
if nl > l
938938
ccall(:jl_array_grow_end, Cvoid, (Any, UInt), a, nl-l)
939-
else
939+
elseif nl != l
940940
if nl < 0
941941
throw(ArgumentError("new length must be ≥ 0"))
942942
end

src/array.c

+4
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,8 @@ JL_DLLEXPORT void jl_array_del_beg(jl_array_t *a, size_t dec)
999999
jl_bounds_error_int((jl_value_t*)a, dec);
10001000
if (__unlikely(a->flags.isshared))
10011001
array_try_unshare(a);
1002+
if (dec == 0)
1003+
return;
10021004
jl_array_del_at_beg(a, 0, dec, n);
10031005
}
10041006

@@ -1009,6 +1011,8 @@ JL_DLLEXPORT void jl_array_del_end(jl_array_t *a, size_t dec)
10091011
jl_bounds_error_int((jl_value_t*)a, 0);
10101012
if (__unlikely(a->flags.isshared))
10111013
array_try_unshare(a);
1014+
if (dec == 0)
1015+
return;
10121016
jl_array_del_at_end(a, n - dec, dec, n);
10131017
}
10141018

test/arrayops.jl

+15
Original file line numberDiff line numberDiff line change
@@ -2342,4 +2342,19 @@ Base.view(::T25958, args...) = args
23422342
@test t[end,1,end] == @view(t[end,1,end]) == @views t[end,1,end]
23432343
@test t[end,end,1] == @view(t[end,end,1]) == @views t[end,end,1]
23442344
@test t[end,end,end] == @view(t[end,end,end]) == @views t[end,end,end]
2345+
end
2346+
2347+
# resize! sets the last element to zero when element size is one byte
2348+
@testset "check that resize! is a no-op when size does not change" for T in (Int, UInt8, Int8)
2349+
x = Vector{T}(uninitialized, 1)
2350+
resize!(x, 0)
2351+
unsafe_store!(pointer(x), 1, 1)
2352+
resize!(x, 0)
2353+
@test unsafe_load(pointer(x), 1) == 1
2354+
2355+
x = Vector{T}(uninitialized, 2)
2356+
resize!(x, 1)
2357+
unsafe_store!(pointer(x), 1, 2)
2358+
resize!(x, 1)
2359+
@test unsafe_load(pointer(x), 2) == 1
23452360
end

test/strings/basic.jl

+10
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ using Random
88
@test String("abc!") == "abc!"
99
@test String(0x61:0x63) == "abc"
1010

11+
# Check that resizing empty source vector does not corrupt string
12+
b = IOBuffer()
13+
write(b, "ab")
14+
x = take!(b)
15+
s = String(x)
16+
resize!(x, 0)
17+
@test s == "ab"
18+
resize!(x, 1)
19+
@test s == "ab"
20+
1121
@test isempty(string())
1222
@test eltype(GenericString) == Char
1323
@test firstindex("abc") == 1

0 commit comments

Comments
 (0)