diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 3d9d2a9535cbd..75cfabf3e8478 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -974,7 +974,7 @@ static void spl_array_set_array(zval *object, spl_array_object *intern, zval *ar //??? TODO: try to avoid array duplication ZVAL_ARR(&intern->array, zend_array_dup(Z_ARR_P(array))); - if (intern->is_child) { + if (intern->is_child && intern->bucket) { Z_TRY_DELREF(intern->bucket->val); /* * replace bucket->val with copied array, so the changes between @@ -1018,6 +1018,10 @@ static void spl_array_set_array(zval *object, spl_array_object *intern, zval *ar intern->ht_iter = (uint32_t)-1; } + if (intern->is_child) { + intern->bucket = NULL; + } + zval_ptr_dtor(&garbage); } /* }}} */ diff --git a/ext/spl/tests/gh21499.phpt b/ext/spl/tests/gh21499.phpt new file mode 100644 index 0000000000000..856437951aa2a --- /dev/null +++ b/ext/spl/tests/gh21499.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-21499: RecursiveArrayIterator getChildren UAF after parent free +--FILE-- +getChildren(); +unset($it); +$child->__construct([2, 3]); +var_dump($child->getArrayCopy()); +?> +--EXPECT-- +array(2) { + [0]=> + int(2) + [1]=> + int(3) +}