Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Zend/zend.c
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,12 @@ ZEND_API void zend_print_flat_zval_r(zval *expr)

static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /* {{{ */
{
#ifdef ZEND_CHECK_STACK_LIMIT
if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) {
zend_call_stack_size_error();
return;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not propagate errors so there should be some exception check.

}
#endif
switch (Z_TYPE_P(expr)) {
case IS_ARRAY:
smart_str_appends(buf, "Array\n");
Expand Down
42 changes: 42 additions & 0 deletions ext/standard/tests/general_functions/gh24605_stack_guard.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
--TEST--
GH-24605 (var_export(), print_r() and unserialize() segfault on deep nesting)
--SKIPIF--
<?php
if (ini_get('zend.max_allowed_stack_size') === false) {
die('skip No stack limit support');
}
if (getenv('SKIP_ASAN')) {
die('skip ASAN needs different stack limit setting due to more stack space usage');
}
?>
--INI--
zend.max_allowed_stack_size=512K
--FILE--
<?php
$a = 0;
for ($i = 0; $i < 3000; $i++) {
$a = [$a];
}
$u = str_repeat('a:1:{i:0;', 3000) . 'i:0;' . str_repeat('}', 3000);

$calls = [
'var_export' => static fn() => var_export($a),
'print_r' => static fn() => print_r($a, true),
'unserialize' => static fn() => unserialize($u),
];

foreach ($calls as $name => $call) {
try {
$call();
echo $name, ": no error\n";
} catch (\Error $e) {
echo $name, ': ',
str_contains($e->getMessage(), 'Maximum call stack size') ? 'stack error' : 'other error',
"\n";
}
}
?>
--EXPECT--
var_export: stack error
print_r: stack error
unserialize: stack error
6 changes: 6 additions & 0 deletions ext/standard/var.c
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,12 @@ static zend_result php_object_element_export(zval *zv, zend_ulong index, zend_st

PHPAPI zend_result php_var_export_ex(zval *struc, int level, smart_str *buf) /* {{{ */
{
#ifdef ZEND_CHECK_STACK_LIMIT
if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) {
zend_call_stack_size_error();
return FAILURE;
}
#endif
Comment on lines +541 to +546

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already handled by #24671 so it should be dropped.

HashTable *myht;
zend_string *ztmp, *ztmp2;
zend_ulong index;
Expand Down
6 changes: 6 additions & 0 deletions ext/standard/var_unserializer.re
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,12 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)

static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
{
#ifdef ZEND_CHECK_STACK_LIMIT
if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) {
zend_call_stack_size_error();
return 0;
}
#endif
const unsigned char *cursor, *limit, *marker, *start;
zval *rval_ref;

Expand Down
Loading