diff --git a/Zend/tests/gh25299.phpt b/Zend/tests/gh25299.phpt new file mode 100644 index 000000000000..b1fe486b0f58 --- /dev/null +++ b/Zend/tests/gh25299.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-25299 (Exception string code is lost after unserialize()) +--CREDITS-- +tacman +--FILE-- +getCode()); + +$e = unserialize('O:9:"Exception":1:{s:7:"' . "\0*\0" . 'code";a:0:{}}'); +var_dump($e->getCode()); + +?> +--EXPECTF-- +string(5) "HY000" + +Warning: Undefined property: Exception::$code in %s on line %d +NULL diff --git a/Zend/tests/gh25299_ref.phpt b/Zend/tests/gh25299_ref.phpt new file mode 100644 index 000000000000..c4e0d84a821c --- /dev/null +++ b/Zend/tests/gh25299_ref.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-25299: Exception::__wakeup() keeps message and code held by reference +--FILE-- +message = &$this->m; + $this->code = &$this->c; + } +} + +$e = unserialize(serialize(new MyException())); +var_dump($e->getMessage(), $e->getCode()); + +?> +--EXPECT-- +string(1) "m" +int(5) diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 6138e302bb5d..e6ec1bf90ee5 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -347,9 +347,10 @@ ZEND_METHOD(Exception, __construct) /* }}} */ /* {{{ Exception unserialize checks */ -#define CHECK_EXC_TYPE(id, type) \ +#define CHECK_EXC_TYPE(id, type_mask) \ pvalue = zend_read_property_ex(i_get_exception_base(Z_OBJ_P(object)), Z_OBJ_P(object), ZSTR_KNOWN(id), 1, &value); \ - if (Z_TYPE_P(pvalue) != IS_NULL && Z_TYPE_P(pvalue) != type) { \ + ZVAL_DEREF(pvalue); \ + if (Z_TYPE_P(pvalue) != IS_NULL && !((type_mask) & (1u << Z_TYPE_P(pvalue)))) { \ zend_unset_property(i_get_exception_base(Z_OBJ_P(object)), Z_OBJ_P(object), ZSTR_VAL(ZSTR_KNOWN(id)), ZSTR_LEN(ZSTR_KNOWN(id))); \ } @@ -359,8 +360,8 @@ ZEND_METHOD(Exception, __wakeup) zval value, *pvalue; zval *object = ZEND_THIS; - CHECK_EXC_TYPE(ZEND_STR_MESSAGE, IS_STRING); - CHECK_EXC_TYPE(ZEND_STR_CODE, IS_LONG); + CHECK_EXC_TYPE(ZEND_STR_MESSAGE, MAY_BE_STRING); + CHECK_EXC_TYPE(ZEND_STR_CODE, MAY_BE_LONG | MAY_BE_STRING); /* The type of all other properties is enforced through typed properties. */ } /* }}} */