diff --git a/Zend/tests/stack_limit/stack_limit_001.phpt b/Zend/tests/stack_limit/stack_limit_001.phpt index 2de5d28134ce7..ea9ba4e8b8ca3 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 53fc707ca6a5e..db47192838bf0 100644 --- a/Zend/tests/stack_limit/stack_limit_002.phpt +++ b/Zend/tests/stack_limit/stack_limit_002.phpt @@ -26,13 +26,6 @@ class Test2 { } } -class Test3 { - public function __sleep() - { - serialize($this); - } -} - function replace() { return preg_replace_callback('#.#', function () { return replace(); @@ -52,12 +45,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) { @@ -82,4 +69,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 0000000000000..677982141abcd --- /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 4f04ff6c0deb3..3d53ebf5137a4 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -986,6 +986,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; @@ -995,6 +1004,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. */