diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 87457652ec1a8..f4dff10786440 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -106,15 +106,20 @@ static void spl_fixedarray_resize(spl_fixedarray *array, zend_long size) /* {{{ /* clearing the array */ if (size == 0) { - zend_long i; - - for (i = 0; i < array->size; i++) { - zval_ptr_dtor(&(array->elements[i])); - } + if (array->elements != NULL) { + zend_long i; + zval *elements = array->elements; + zend_long old_size = array->size; - if (array->elements) { - efree(array->elements); array->elements = NULL; + array->size = 0; + + for (i = 0; i < old_size; i++) { + zval_ptr_dtor(&(elements[i])); + } + + efree(elements); + return; } } else if (size > array->size) { array->elements = safe_erealloc(array->elements, size, sizeof(zval), 0); diff --git a/ext/spl/tests/bug80663.phpt b/ext/spl/tests/bug80663.phpt new file mode 100644 index 0000000000000..9e359cc60ef6d --- /dev/null +++ b/ext/spl/tests/bug80663.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #80663 (Recursive SplFixedArray::setSize() may cause double-free) +--FILE-- +setSize(0); + } +} + +$obj = new SplFixedArray(1000); +$obj[0] = new InvalidDestructor(); +$obj->setSize(0); +?> +--EXPECT--