diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index bceaf2be93daf..255cc7457690f 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -43,6 +43,8 @@ ZEND_GET_MODULE(spl_fixedarray) typedef struct _spl_fixedarray { /* {{{ */ zend_long size; zval *elements; + unsigned int is_resizing:1; + unsigned int reserved:31; } spl_fixedarray; /* }}} */ @@ -88,6 +90,7 @@ static void spl_fixedarray_init(spl_fixedarray *array, zend_long size) /* {{{ */ array->elements = NULL; array->size = 0; } + array->is_resizing = 0; } /* }}} */ @@ -104,6 +107,8 @@ static void spl_fixedarray_resize(spl_fixedarray *array, zend_long size) /* {{{ return; } + array->is_resizing = 1; + /* clearing the array */ if (size == 0) { zend_long i; @@ -129,6 +134,7 @@ static void spl_fixedarray_resize(spl_fixedarray *array, zend_long size) /* {{{ } array->size = size; + array->is_resizing = 0; } /* }}} */ @@ -738,6 +744,11 @@ SPL_METHOD(SplFixedArray, setSize) intern = Z_SPLFIXEDARRAY_P(object); + if (intern->array.is_resizing) { + zend_throw_exception_ex(spl_ce_LogicException, 0, "recursive resize is not allowed"); + return; + } + spl_fixedarray_resize(&intern->array, size); RETURN_TRUE; } diff --git a/ext/spl/tests/bug80663.phpt b/ext/spl/tests/bug80663.phpt new file mode 100644 index 0000000000000..049dc0e908c96 --- /dev/null +++ b/ext/spl/tests/bug80663.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #80663 (Recursive SplFixedArray::setSize() may cause double-free) +--FILE-- +setSize(0); + } catch (LogicException $ex) { + echo $ex->getMessage(); + } + } +} + +$obj = new SplFixedArray(1000); +$obj[0] = new InvalidDestructor(); +$obj->setSize(0); +?> +--EXPECT-- +recursive resize is not allowed