diff --git a/Zend/tests/stack_limit/stack_limit_001.phpt b/Zend/tests/stack_limit/stack_limit_001.phpt index a7d9e4c50e8..73cc3c08fe9 100644 --- a/Zend/tests/stack_limit/stack_limit_001.phpt +++ b/Zend/tests/stack_limit/stack_limit_001.phpt @@ -27,13 +27,6 @@ class Test2 { } } -class Test3 { - public function __sleep() - { - serialize($this); - } -} - function replace() { return preg_replace_callback('#.#', function () { return replace(); @@ -52,12 +45,6 @@ try { echo $e->getMessage(), "\n"; } -try { - serialize(new Test3); -} catch (Error $e) { - echo $e->getMessage(), "\n"; -} - try { replace(); } catch (Error $e) { @@ -79,4 +66,3 @@ array(4) { Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion? Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion? Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion? -Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion? diff --git a/Zend/tests/stack_limit/stack_limit_002.phpt b/Zend/tests/stack_limit/stack_limit_002.phpt index 44fab205f2f..64a11e1b263 100644 --- a/Zend/tests/stack_limit/stack_limit_002.phpt +++ b/Zend/tests/stack_limit/stack_limit_002.phpt @@ -25,13 +25,6 @@ class Test2 { } } -class Test3 { - public function __sleep() - { - serialize($this); - } -} - function replace() { return preg_replace_callback('#.#', function () { return replace(); @@ -51,12 +44,6 @@ $fiber = new Fiber(function (): void { echo $e->getMessage(), "\n"; } - try { - serialize(new Test3); - } catch (Error $e) { - echo $e->getMessage(), "\n"; - } - try { replace(); } catch (Error $e) { @@ -81,4 +68,3 @@ array(4) { Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion? Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion? Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion? -Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion? diff --git a/ext/standard/tests/serialize/gh15169.phpt b/ext/standard/tests/serialize/gh15169.phpt new file mode 100644 index 00000000000..677982141ab --- /dev/null +++ b/ext/standard/tests/serialize/gh15169.phpt @@ -0,0 +1,35 @@ +--TEST-- +GH-15169 (stack overflow when var serialization in ext/standard/var) +--SKIPIF-- + +--INI-- +zend.max_allowed_stack_size=512K +--FILE-- +next = $newNode; + $node = $newNode; +} + +try { + serialize($firstNode); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +Maximum call stack size reached. Infinite recursion? diff --git a/ext/standard/var.c b/ext/standard/var.c index 0d08a0a3383..b161caeeda6 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -1033,6 +1033,15 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, HashTable *ht, } /* }}} */ +static zend_always_inline bool php_serialize_check_stack_limit(void) +{ +#ifdef ZEND_CHECK_STACK_LIMIT + return zend_call_stack_overflowed(EG(stack_limit)); +#else + return false; +#endif +} + static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_data_t var_hash, bool in_rcn_array, bool is_root) /* {{{ */ { zend_long var_already; @@ -1042,6 +1051,11 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_ return; } + if (UNEXPECTED(php_serialize_check_stack_limit())) { + zend_throw_error(NULL, "Maximum call stack size reached. Infinite recursion?"); + return; + } + if (var_hash && (var_already = php_add_var_hash(var_hash, struc, in_rcn_array))) { if (var_already == -1) { /* Reference to an object that failed to serialize, replace with null. */