@@ -48,6 +48,8 @@ typedef struct _spl_fixedarray {
4848 zend_long size ;
4949 /* It is possible to resize this, so this can't be combined with the object */
5050 zval * elements ;
51+ /* If positive, it's a resize within a resize and the value gives the desired size. If -1, it's not. */
52+ zend_long cached_resize ;
5153} spl_fixedarray ;
5254
5355typedef struct _spl_fixedarray_object {
@@ -115,6 +117,7 @@ static void spl_fixedarray_init(spl_fixedarray *array, zend_long size)
115117 } else {
116118 spl_fixedarray_default_ctor (array );
117119 }
120+ array -> cached_resize = -1 ;
118121}
119122
120123/* Copies the range [begin, end) into the fixedarray, beginning at `offset`.
@@ -146,6 +149,7 @@ static void spl_fixedarray_copy_ctor(spl_fixedarray *to, spl_fixedarray *from)
146149 */
147150static void spl_fixedarray_dtor_range (spl_fixedarray * array , zend_long from , zend_long to )
148151{
152+ array -> size = from ;
149153 zval * begin = array -> elements + from , * end = array -> elements + to ;
150154 while (begin != end ) {
151155 zval_ptr_dtor (begin ++ );
@@ -181,19 +185,35 @@ static void spl_fixedarray_resize(spl_fixedarray *array, zend_long size)
181185 return ;
182186 }
183187
188+ if (UNEXPECTED (array -> cached_resize >= 0 )) {
189+ /* We're already resizing, so just remember the desired size.
190+ * The resize will happen later. */
191+ array -> cached_resize = size ;
192+ return ;
193+ }
194+ array -> cached_resize = size ;
195+
184196 /* clearing the array */
185197 if (size == 0 ) {
186198 spl_fixedarray_dtor (array );
187199 array -> elements = NULL ;
200+ array -> size = 0 ;
188201 } else if (size > array -> size ) {
189202 array -> elements = safe_erealloc (array -> elements , size , sizeof (zval ), 0 );
190203 spl_fixedarray_init_elems (array , array -> size , size );
204+ array -> size = size ;
191205 } else { /* size < array->size */
206+ /* Size set in spl_fixedarray_dtor_range() */
192207 spl_fixedarray_dtor_range (array , size , array -> size );
193208 array -> elements = erealloc (array -> elements , sizeof (zval ) * size );
194209 }
195210
196- array -> size = size ;
211+ /* If resized within the destructor, take the last resize command and perform it */
212+ zend_long cached_resize = array -> cached_resize ;
213+ array -> cached_resize = -1 ;
214+ if (cached_resize != size ) {
215+ spl_fixedarray_resize (array , cached_resize );
216+ }
197217}
198218
199219static HashTable * spl_fixedarray_object_get_gc (zend_object * obj , zval * * table , int * n )
0 commit comments