Skip to content

Commit de98c0c

Browse files
authored
Set array size only after allocating the new memory portion (#58848)
The `.size` of an array might be getting set too early; before the memory is actually allocated, resulting in larger race windows for inconsistencies (in particular, during finalizers on this thread) to manifest. This helps keep those instructions more nearly consecutive to each other so there is a smaller window for races to be visible, in typical non-adversarial situations.
1 parent 75ea2c7 commit de98c0c

File tree

1 file changed

+7
-4
lines changed

1 file changed

+7
-4
lines changed

base/array.jl

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,12 +1145,13 @@ function _growbeg!(a::Vector, delta::Integer)
11451145
len = length(a)
11461146
offset = memoryrefoffset(ref)
11471147
newlen = len + delta
1148-
setfield!(a, :size, (newlen,))
11491148
# if offset is far enough advanced to fit data in existing memory without copying
11501149
if delta <= offset - 1
11511150
setfield!(a, :ref, @inbounds memoryref(ref, 1 - delta))
1151+
setfield!(a, :size, (newlen,))
11521152
else
11531153
@noinline _growbeg_internal!(a, delta, len)
1154+
setfield!(a, :size, (newlen,))
11541155
end
11551156
return
11561157
end
@@ -1200,11 +1201,11 @@ function _growend!(a::Vector, delta::Integer)
12001201
len = length(a)
12011202
newlen = len + delta
12021203
offset = memoryrefoffset(ref)
1203-
setfield!(a, :size, (newlen,))
12041204
newmemlen = offset + newlen - 1
12051205
if memlen < newmemlen
12061206
@noinline _growend_internal!(a, delta, len)
12071207
end
1208+
setfield!(a, :size, (newlen,))
12081209
return
12091210
end
12101211

@@ -1222,7 +1223,6 @@ function _growat!(a::Vector, i::Integer, delta::Integer)
12221223
memlen = length(mem)
12231224
newlen = len + delta
12241225
offset = memoryrefoffset(ref)
1225-
setfield!(a, :size, (newlen,))
12261226
newmemlen = offset + newlen - 1
12271227

12281228
# which side would we rather grow into?
@@ -1232,11 +1232,13 @@ function _growat!(a::Vector, i::Integer, delta::Integer)
12321232
newref = @inbounds memoryref(mem, offset - delta)
12331233
unsafe_copyto!(newref, ref, i)
12341234
setfield!(a, :ref, newref)
1235+
setfield!(a, :size, (newlen,))
12351236
for j in i:i+delta-1
12361237
@inbounds _unsetindex!(a, j)
12371238
end
12381239
elseif !prefer_start && memlen >= newmemlen
12391240
unsafe_copyto!(mem, offset - 1 + delta + i, mem, offset - 1 + i, len - i + 1)
1241+
setfield!(a, :size, (newlen,))
12401242
for j in i:i+delta-1
12411243
@inbounds _unsetindex!(a, j)
12421244
end
@@ -1250,6 +1252,7 @@ function _growat!(a::Vector, i::Integer, delta::Integer)
12501252
unsafe_copyto!(newref, ref, i-1)
12511253
unsafe_copyto!(newmem, newoffset + delta + i - 1, mem, offset + i - 1, len - i + 1)
12521254
setfield!(a, :ref, newref)
1255+
setfield!(a, :size, (newlen,))
12531256
end
12541257
end
12551258

@@ -1265,11 +1268,11 @@ function _deletebeg!(a::Vector, delta::Integer)
12651268
@inbounds _unsetindex!(a, i)
12661269
end
12671270
newlen = len - delta
1271+
setfield!(a, :size, (newlen,))
12681272
if newlen != 0 # if newlen==0 we could accidentally index past the memory
12691273
newref = @inbounds memoryref(a.ref, delta + 1)
12701274
setfield!(a, :ref, newref)
12711275
end
1272-
setfield!(a, :size, (newlen,))
12731276
return
12741277
end
12751278
function _deleteend!(a::Vector, delta::Integer)

0 commit comments

Comments
 (0)