From f92a03627a51a3e440b73795fb2a34a888f23b8d Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 1 Sep 2020 15:14:32 +0200 Subject: Check for null EX(func) in write_property This can happen if zend_call_function inserted a dummy frame, and we already switched to the dummy frame in leave_helper, and an exception is thrown during CV destruction. Fixes oss-fuzz #25343. --- Zend/tests/ex_func_null_during_property_write.phpt | 25 ++++++++++++++++++++++ Zend/zend_object_handlers.c | 13 ++++++++--- 2 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 Zend/tests/ex_func_null_during_property_write.phpt diff --git a/Zend/tests/ex_func_null_during_property_write.phpt b/Zend/tests/ex_func_null_during_property_write.phpt new file mode 100644 index 0000000000..6a253f760e --- /dev/null +++ b/Zend/tests/ex_func_null_during_property_write.phpt @@ -0,0 +1,25 @@ +--TEST-- +EX(func) can be null during write_property in an edge case +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Error: Object of class a could not be converted to string in %s:%d +Stack trace: +#0 %s(%d): a->__destruct() +#1 {main} + +Next Exception in %s:%d +Stack trace: +#0 %s(%d): a->__destruct() +#1 {main} + thrown in %s on line %d diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index e1220ad0ee..a0a5e48dee 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -809,6 +809,13 @@ exit: } /* }}} */ +static zend_always_inline zend_bool property_uses_strict_types() { + zend_execute_data *execute_data = EG(current_execute_data); + return execute_data + && execute_data->func + && ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data)); +} + ZEND_API zval *zend_std_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */ { zend_object *zobj; @@ -833,7 +840,7 @@ ZEND_API zval *zend_std_write_property(zval *object, zval *member, zval *value, if (UNEXPECTED(prop_info)) { ZVAL_COPY_VALUE(&tmp, value); - if (UNEXPECTED(!zend_verify_property_type(prop_info, &tmp, EG(current_execute_data) && ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data))))) { + if (UNEXPECTED(!zend_verify_property_type(prop_info, &tmp, property_uses_strict_types()))) { Z_TRY_DELREF_P(value); variable_ptr = &EG(error_zval); goto exit; @@ -842,7 +849,7 @@ ZEND_API zval *zend_std_write_property(zval *object, zval *member, zval *value, } found: - zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EG(current_execute_data) && ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data))); + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, property_uses_strict_types()); goto exit; } if (Z_PROP_FLAG_P(variable_ptr) == IS_PROP_UNINIT) { @@ -898,7 +905,7 @@ write_std_property: if (UNEXPECTED(prop_info)) { ZVAL_COPY_VALUE(&tmp, value); - if (UNEXPECTED(!zend_verify_property_type(prop_info, &tmp, ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data))))) { + if (UNEXPECTED(!zend_verify_property_type(prop_info, &tmp, property_uses_strict_types()))) { zval_ptr_dtor(value); goto exit; } -- cgit v1.2.1