From 2d6684091fc365df01905be51d906655385da3ba Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 21 Sep 2021 16:30:23 +0200 Subject: [PATCH] Fix #80663: Recursive SplFixedArray::setSize() may cause double-free We address the `::setSize(0)` case by setting `array->element = NULL` and `array->size = 0` before we destroy the elements. Co-authored-by: Tyson Andre Closes GH-7503. --- NEWS | 6 +++++- ext/spl/spl_fixedarray.c | 19 ++++++++++++------- ext/spl/tests/bug80663.phpt | 15 +++++++++++++++ 3 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 ext/spl/tests/bug80663.phpt diff --git a/NEWS b/NEWS index 9a105842d8f..8a4e9a09bd5 100644 --- a/NEWS +++ b/NEWS @@ -20,11 +20,15 @@ PHP NEWS - PCRE: . Fixed bug #81424 (PCRE2 10.35 JIT performance regression). (cmb) +- SPL: + . Fixed bug #80663 (Recursive SplFixedArray::setSize() may cause double-free). + (cmb, Nikita, Tyson Andre) + - XML: . Fixed bug #70962 (XML_OPTION_SKIP_WHITE strips embedded whitespace). (Aliaksandr Bystry, cmb) -23 Dep 2021, PHP 7.4.24 +23 Sep 2021, PHP 7.4.24 - Core: . Fixed bug #81302 (Stream position after stream filter removed). (cmb) diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 87457652ec1..f4dff107864 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; + if (array->elements != NULL) { + zend_long i; + zval *elements = array->elements; + zend_long old_size = array->size; - for (i = 0; i < array->size; i++) { - zval_ptr_dtor(&(array->elements[i])); - } - - 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 00000000000..9e359cc60ef --- /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--