diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index 5f5fbca70d4..aff414e7864 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -739,8 +739,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) { + } +}