From 7a3f25e370aa3be594de0873b8d67ae7ad7a21f6 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 25 Nov 2020 12:25:07 +0100 Subject: [PATCH] Fix ref source management during unserialization Only register the slot for adding ref sources later if we didn't immediately register one. Also avoids leaking a ref source if it is added early and the assignment fails. Fixes oss-fuzz #27628. --- ...typed_property_ref_assignment_failure.phpt | 21 +++++++++++++++++++ ext/standard/var_unserializer.re | 21 +++++++++---------- 2 files changed, 31 insertions(+), 11 deletions(-) create mode 100644 ext/standard/tests/serialize/typed_property_ref_assignment_failure.phpt diff --git a/ext/standard/tests/serialize/typed_property_ref_assignment_failure.phpt b/ext/standard/tests/serialize/typed_property_ref_assignment_failure.phpt new file mode 100644 index 0000000000..2e4b576cc2 --- /dev/null +++ b/ext/standard/tests/serialize/typed_property_ref_assignment_failure.phpt @@ -0,0 +1,21 @@ +--TEST-- +Failure to assign ref to typed property +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECT-- +Cannot assign stdClass to property Test::$prop of type int diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 6680e00645..0143d94c70 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -560,17 +560,6 @@ string_key: Z_TRY_DELREF_P(old_data); ZVAL_COPY_VALUE(old_data, &d); data = old_data; - - if (UNEXPECTED(info)) { - /* Remember to which property this slot belongs, so we can add a - * type source if it is turned into a reference lateron. */ - if (!(*var_hash)->ref_props) { - (*var_hash)->ref_props = emalloc(sizeof(HashTable)); - zend_hash_init((*var_hash)->ref_props, 8, NULL, NULL, 0); - } - zend_hash_index_update_ptr( - (*var_hash)->ref_props, (zend_uintptr_t) data, info); - } } else { var_push_dtor(var_hash, old_data); data = zend_hash_update_ind(ht, Z_STR(key), &d); @@ -600,8 +589,18 @@ string_key: zval_ptr_dtor_nogc(&key); goto failure; } + if (Z_ISREF_P(data)) { ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(data), info); + } else { + /* Remember to which property this slot belongs, so we can add a + * type source if it is turned into a reference lateron. */ + if (!(*var_hash)->ref_props) { + (*var_hash)->ref_props = emalloc(sizeof(HashTable)); + zend_hash_init((*var_hash)->ref_props, 8, NULL, NULL, 0); + } + zend_hash_index_update_ptr( + (*var_hash)->ref_props, (zend_uintptr_t) data, info); } } -- 2.50.1