diff --git a/NEWS b/NEWS index ae8972b71c0..26118955d01 100644 --- a/NEWS +++ b/NEWS @@ -76,6 +76,7 @@ PHP NEWS . Fixed bug GH-16337 (Use-after-free in SplHeap). (nielsdos) . Fixed bug GH-16464 (Use-after-free in SplDoublyLinkedList::offsetSet()). (ilutov) + . Fixed bug GH-16479 (Use-after-free in SplObjectStorage::setInfo()). (ilutov) - Standard: . Fixed bug GH-16293 (Failed assertion when throwing in assert() callback with diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index 00f25ecbbc4..3ee7e2689f7 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -744,8 +744,10 @@ PHP_METHOD(SplObjectStorage, setInfo) if ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) == NULL) { RETURN_NULL(); } - zval_ptr_dtor(&element->inf); + zval garbage; + ZVAL_COPY_VALUE(&garbage, &element->inf); ZVAL_COPY(&element->inf, inf); + zval_ptr_dtor(&garbage); } /* }}} */ /* {{{ Moves position forward */ diff --git a/ext/spl/tests/gh16479.phpt b/ext/spl/tests/gh16479.phpt new file mode 100644 index 00000000000..5309a450b9d --- /dev/null +++ b/ext/spl/tests/gh16479.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-16479: Use-after-free in SplObjectStorage::setInfo() +--FILE-- +removeAll($store); + } +} + +$o = new stdClass; +$store = new SplObjectStorage; +$store[$o] = new C; +$store->setInfo(1); +var_dump($store); + +?> +--EXPECT-- +object(SplObjectStorage)#2 (1) { + ["storage":"SplObjectStorage":private]=> + array(0) { + } +}