Skip to content

Commit

Permalink
Support stack limit in phpdbg SAPI
Browse files Browse the repository at this point in the history
Add a stack limit check in zend_vm_call_opcode_handler for SAPIs that do not use
execute_ex().
  • Loading branch information
arnaud-lb committed Sep 25, 2024
1 parent f35ad56 commit ecf8e3e
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 0 deletions.
39 changes: 39 additions & 0 deletions Zend/tests/stack_limit/gh16041_001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
--TEST--
GH-16041 001: Stack overflow in phpdbg
--SKIPIF--
<?php
if (ini_get('zend.max_allowed_stack_size') === false) {
die('skip No stack limit support');
}
?>
--INI--
zend.max_allowed_stack_size=512K
--PHPDBG--
set pagination off
run
continue
quit
--FILE--
<?php

class Canary {
public function __destruct() {
new Canary();
}
}

new Canary();

?>
--EXPECTF--
[Successful compilation of %sgh16041_001.php]
prompt> prompt> [Uncaught Error in %s on line %d: Maximum call stack size of %d bytes%s
>00005: new Canary();
00006: }
00007: }
prompt> [Uncaught Error in %s on line %d]
Error: Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion? in %s:%d
Stack trace:
#0 %s(%d): Canary->__destruct()
%a
prompt>
33 changes: 33 additions & 0 deletions Zend/tests/stack_limit/gh16041_002.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
--TEST--
GH-16041 002: Stack overflow in phpdbg
--SKIPIF--
<?php
if (ini_get('zend.max_allowed_stack_size') === false) {
die('skip No stack limit support');
}
?>
--INI--
zend.max_allowed_stack_size=512K
--PHPDBG--
set pagination off
run
quit
--FILE--
<?php

function map() {
array_map('map', [1]);
}

try {
map();
} catch (\Throwable $e) {
printf("%s: %s\n", $e::class, $e->getMessage());
}

?>
--EXPECTF--
[Successful compilation of %sgh16041_002.php]
prompt> prompt> Error: Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion?
[Script ended normally]
prompt>
11 changes: 11 additions & 0 deletions Zend/zend_vm_execute.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions Zend/zend_vm_gen.php
Original file line number Diff line number Diff line change
Expand Up @@ -2974,6 +2974,17 @@ function gen_vm($def, $skel) {
out($f, "#endif\n");
out($f, "\n");
out($f, "\tLOAD_OPLINE();\n");
out($f, "\n");
out($f, "\t#ifdef ZEND_CHECK_STACK_LIMIT\n");
out($f, "\t\tif (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) {\n");
out($f, "\t\t\tzend_call_stack_size_error();\n");
out($f, "\t\t\t/* No opline was executed before exception */\n");
out($f, "\t\t\tEG(opline_before_exception) = NULL;\n");
out($f, "\t\t\tLOAD_OPLINE();\n");
out($f, "\t\t\t/* Fall through to handle exception below. */\n");
out($f, "\t\t}\n");
out($f, "\t#endif /* ZEND_CHECK_STACK_LIMIT */\n");
out($f, "\n");
out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n");
if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) {
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
Expand Down

0 comments on commit ecf8e3e

Please sign in to comment.