mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Limit stack size (#9104)
This commit is contained in:
parent
dc54e04ed4
commit
a11c8a3039
41 changed files with 1844 additions and 12 deletions
|
@ -28,6 +28,7 @@ environment:
|
|||
#PDO_MYSQL_TEST_PASS: Password12!
|
||||
#PGSQL_TEST_CONNSTR: "host=127.0.0.1 dbname=test port=5432 user=postgres password=Password12!"
|
||||
#PDO_PGSQL_TEST_DSN: "pgsql:host=127.0.0.1 port=5432 dbname=test user=postgres password=Password12!"
|
||||
STACK_LIMIT_DEFAULTS_CHECK: 1
|
||||
#build permutations
|
||||
matrix:
|
||||
- THREAD_SAFE: 0
|
||||
|
|
|
@ -201,4 +201,5 @@ freebsd_task:
|
|||
tests_script:
|
||||
- export SKIP_IO_CAPTURE_TESTS=1
|
||||
- export CI_NO_IPV6=1
|
||||
- export STACK_LIMIT_DEFAULTS_CHECK=1
|
||||
- sapi/cli/php run-tests.php -P -q -j2 -g FAIL,BORK,LEAK,XLEAK --no-progress --offline --show-diff --show-slow 1000 --set-timeout 120 -d zend_extension=opcache.so
|
||||
|
|
1
.github/actions/test-linux/action.yml
vendored
1
.github/actions/test-linux/action.yml
vendored
|
@ -30,6 +30,7 @@ runs:
|
|||
export PDO_OCI_TEST_DSN="oci:dbname=localhost/XEPDB1;charset=AL32UTF8"
|
||||
export SKIP_IO_CAPTURE_TESTS=1
|
||||
export TEST_PHP_JUNIT=junit.out.xml
|
||||
export STACK_LIMIT_DEFAULTS_CHECK=1
|
||||
sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \
|
||||
-j$(/usr/bin/nproc) \
|
||||
-g FAIL,BORK,LEAK,XLEAK \
|
||||
|
|
1
.github/actions/test-macos/action.yml
vendored
1
.github/actions/test-macos/action.yml
vendored
|
@ -15,6 +15,7 @@ runs:
|
|||
export SKIP_IO_CAPTURE_TESTS=1
|
||||
export CI_NO_IPV6=1
|
||||
export TEST_PHP_JUNIT=junit.out.xml
|
||||
export STACK_LIMIT_DEFAULTS_CHECK=1
|
||||
sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \
|
||||
-j$(sysctl -n hw.ncpu) \
|
||||
-g FAIL,BORK,LEAK,XLEAK \
|
||||
|
|
32
Zend/Zend.m4
32
Zend/Zend.m4
|
@ -146,7 +146,37 @@ _LT_AC_TRY_DLOPEN_SELF([
|
|||
])
|
||||
|
||||
dnl Checks for library functions.
|
||||
AC_CHECK_FUNCS(getpid kill sigsetjmp)
|
||||
AC_CHECK_FUNCS(getpid kill sigsetjmp pthread_getattr_np pthread_attr_get_np pthread_get_stackaddr_np pthread_attr_getstack gettid)
|
||||
|
||||
dnl Test whether the stack grows downwards
|
||||
dnl Assumes contiguous stack
|
||||
AC_MSG_CHECKING(whether the stack grows downwards)
|
||||
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <stdint.h>
|
||||
|
||||
int (*volatile f)(uintptr_t);
|
||||
|
||||
int stack_grows_downwards(uintptr_t arg) {
|
||||
int local;
|
||||
return (uintptr_t)&local < arg;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int local;
|
||||
|
||||
f = stack_grows_downwards;
|
||||
return f((uintptr_t)&local) ? 0 : 1;
|
||||
}
|
||||
]])], [
|
||||
AC_DEFINE([ZEND_STACK_GROWS_DOWNWARDS], 1, [Define if the stack grows downwards])
|
||||
AC_DEFINE([ZEND_CHECK_STACK_LIMIT], 1, [Define if checking the stack limit is supported])
|
||||
AC_MSG_RESULT(yes)
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
|
||||
ZEND_CHECK_FLOAT_PRECISION
|
||||
])
|
||||
|
|
77
Zend/tests/stack_limit/stack_limit_001.phpt
Normal file
77
Zend/tests/stack_limit/stack_limit_001.phpt
Normal file
|
@ -0,0 +1,77 @@
|
|||
--TEST--
|
||||
Stack limit 001 - Stack limit checks with max_allowed_stack_size detection
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--INI--
|
||||
; The test may use a large amount of memory on systems with a large stack limit
|
||||
memory_limit=2G
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(zend_test_zend_call_stack_get());
|
||||
|
||||
class Test1 {
|
||||
public function __destruct() {
|
||||
new Test1;
|
||||
}
|
||||
}
|
||||
|
||||
class Test2 {
|
||||
public function __clone() {
|
||||
clone $this;
|
||||
}
|
||||
}
|
||||
|
||||
class Test3 {
|
||||
public function __sleep()
|
||||
{
|
||||
serialize($this);
|
||||
}
|
||||
}
|
||||
|
||||
function replace() {
|
||||
return preg_replace_callback('#.#', function () {
|
||||
return replace();
|
||||
}, 'x');
|
||||
}
|
||||
|
||||
try {
|
||||
new Test1;
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
clone new Test2;
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
serialize(new Test3);
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
replace();
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(4) {
|
||||
["base"]=>
|
||||
string(%d) "0x%x"
|
||||
["max_size"]=>
|
||||
string(%d) "0x%x"
|
||||
["position"]=>
|
||||
string(%d) "0x%x"
|
||||
["EG(stack_limit)"]=>
|
||||
string(%d) "0x%x"
|
||||
}
|
||||
Maximum call stack size of %d bytes reached. Infinite recursion?
|
||||
Maximum call stack size of %d bytes reached. Infinite recursion?
|
||||
Maximum call stack size of %d bytes reached. Infinite recursion?
|
||||
Maximum call stack size of %d bytes reached. Infinite recursion?
|
80
Zend/tests/stack_limit/stack_limit_002.phpt
Normal file
80
Zend/tests/stack_limit/stack_limit_002.phpt
Normal file
|
@ -0,0 +1,80 @@
|
|||
--TEST--
|
||||
Stack limit 002 - Stack limit checks with max_allowed_stack_size detection (fibers)
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--INI--
|
||||
fiber.stack_size=512k
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(zend_test_zend_call_stack_get());
|
||||
|
||||
class Test1 {
|
||||
public function __destruct() {
|
||||
new Test1;
|
||||
}
|
||||
}
|
||||
|
||||
class Test2 {
|
||||
public function __clone() {
|
||||
clone $this;
|
||||
}
|
||||
}
|
||||
|
||||
class Test3 {
|
||||
public function __sleep()
|
||||
{
|
||||
serialize($this);
|
||||
}
|
||||
}
|
||||
|
||||
function replace() {
|
||||
return preg_replace_callback('#.#', function () {
|
||||
return replace();
|
||||
}, 'x');
|
||||
}
|
||||
|
||||
$fiber = new Fiber(function (): void {
|
||||
try {
|
||||
new Test1;
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
clone new Test2;
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
serialize(new Test3);
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
replace();
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
});
|
||||
|
||||
$fiber->start();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(4) {
|
||||
["base"]=>
|
||||
string(%d) "0x%x"
|
||||
["max_size"]=>
|
||||
string(%d) "0x%x"
|
||||
["position"]=>
|
||||
string(%d) "0x%x"
|
||||
["EG(stack_limit)"]=>
|
||||
string(%d) "0x%x"
|
||||
}
|
||||
Maximum call stack size of %d bytes reached. Infinite recursion?
|
||||
Maximum call stack size of %d bytes reached. Infinite recursion?
|
||||
Maximum call stack size of %d bytes reached. Infinite recursion?
|
||||
Maximum call stack size of %d bytes reached. Infinite recursion?
|
62
Zend/tests/stack_limit/stack_limit_003.phpt
Normal file
62
Zend/tests/stack_limit/stack_limit_003.phpt
Normal file
|
@ -0,0 +1,62 @@
|
|||
--TEST--
|
||||
Stack limit 003 - Stack limit checks with fixed max_allowed_stack_size
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--INI--
|
||||
zend.max_allowed_stack_size=128K
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(zend_test_zend_call_stack_get());
|
||||
|
||||
class Test1 {
|
||||
public function __destruct() {
|
||||
new Test1;
|
||||
}
|
||||
}
|
||||
|
||||
class Test2 {
|
||||
public function __clone() {
|
||||
clone $this;
|
||||
}
|
||||
}
|
||||
|
||||
function replace() {
|
||||
return preg_replace_callback('#.#', function () {
|
||||
return replace();
|
||||
}, 'x');
|
||||
}
|
||||
|
||||
try {
|
||||
new Test1;
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
clone new Test2;
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
replace();
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(4) {
|
||||
["base"]=>
|
||||
string(%d) "0x%x"
|
||||
["max_size"]=>
|
||||
string(%d) "0x%x"
|
||||
["position"]=>
|
||||
string(%d) "0x%x"
|
||||
["EG(stack_limit)"]=>
|
||||
string(%d) "0x%x"
|
||||
}
|
||||
Maximum call stack size of %d bytes reached. Infinite recursion?
|
||||
Maximum call stack size of %d bytes reached. Infinite recursion?
|
||||
Maximum call stack size of %d bytes reached. Infinite recursion?
|
50
Zend/tests/stack_limit/stack_limit_004.phpt
Normal file
50
Zend/tests/stack_limit/stack_limit_004.phpt
Normal file
|
@ -0,0 +1,50 @@
|
|||
--TEST--
|
||||
Stack limit 004 - Stack limit checks with fixed max_allowed_stack_size (fibers)
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(zend_test_zend_call_stack_get());
|
||||
|
||||
class Test1 {
|
||||
public function __destruct() {
|
||||
new Test1;
|
||||
}
|
||||
}
|
||||
|
||||
$callback = function (): int {
|
||||
try {
|
||||
new Test1;
|
||||
} catch (Error $e) {
|
||||
return count($e->getTrace());
|
||||
}
|
||||
|
||||
throw new \Exception();
|
||||
};
|
||||
|
||||
ini_set('fiber.stack_size', '400K');
|
||||
$fiber = new Fiber($callback);
|
||||
$fiber->start();
|
||||
$depth1 = $fiber->getReturn();
|
||||
|
||||
ini_set('fiber.stack_size', '200K');
|
||||
$fiber = new Fiber($callback);
|
||||
$fiber->start();
|
||||
$depth2 = $fiber->getReturn();
|
||||
|
||||
var_dump($depth1 > $depth2);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(4) {
|
||||
["base"]=>
|
||||
string(%d) "0x%x"
|
||||
["max_size"]=>
|
||||
string(%d) "0x%x"
|
||||
["position"]=>
|
||||
string(%d) "0x%x"
|
||||
["EG(stack_limit)"]=>
|
||||
string(%d) "0x%x"
|
||||
}
|
||||
bool(true)
|
64
Zend/tests/stack_limit/stack_limit_005.phpt
Normal file
64
Zend/tests/stack_limit/stack_limit_005.phpt
Normal file
|
@ -0,0 +1,64 @@
|
|||
--TEST--
|
||||
Stack limit 005 - Internal stack limit check in zend_compile_expr()
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--INI--
|
||||
zend.max_allowed_stack_size=128K
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$test
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
;
|
||||
|
||||
--EXPECTF--
|
||||
Fatal error: Maximum call stack size of %d bytes reached during compilation. Try splitting expression in %s on line %d
|
320
Zend/tests/stack_limit/stack_limit_006.phpt
Normal file
320
Zend/tests/stack_limit/stack_limit_006.phpt
Normal file
|
@ -0,0 +1,320 @@
|
|||
--TEST--
|
||||
Stack limit 006 - env size affects __libc_stack_end
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--INI--
|
||||
; TODO
|
||||
memory_limit=2G
|
||||
--ENV--
|
||||
ENV001=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV002=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV003=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV004=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV005=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV006=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV007=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV008=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV009=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV010=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV011=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV012=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV013=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV014=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV015=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV016=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV017=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV018=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV019=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV020=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV021=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV022=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV023=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV024=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV025=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV026=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV027=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV028=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV029=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV030=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV031=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV032=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV033=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV034=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV035=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV036=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV037=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV038=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV039=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV040=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV041=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV042=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV043=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV044=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV045=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV046=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV047=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV048=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV049=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV050=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV051=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV052=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV053=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV054=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV055=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV056=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV057=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV058=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV059=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV060=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV061=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV062=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV063=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV064=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV065=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV066=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV067=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV068=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV069=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV070=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV071=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV072=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV073=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV074=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV075=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV076=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV077=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV078=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV079=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV080=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV081=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV082=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV083=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV084=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV085=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV086=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV087=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV088=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV089=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV090=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV091=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV092=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV093=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV094=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV095=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV096=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV097=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV098=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV099=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV100=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV101=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV102=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV103=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV104=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV105=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV106=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV107=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV108=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV109=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV110=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV111=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV112=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV113=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV114=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV115=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV116=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV117=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV118=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV119=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV120=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV121=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV122=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV123=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV124=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV125=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV126=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV127=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV128=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV129=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV130=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV131=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV132=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV133=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV134=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV135=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV136=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV137=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV138=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV139=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV140=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV141=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV142=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV143=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV144=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV145=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV146=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV147=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV148=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV149=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV150=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV151=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV152=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV153=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV154=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV155=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV156=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV157=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV158=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV159=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV160=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV161=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV162=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV163=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV164=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV165=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV166=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV167=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV168=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV169=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV170=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV171=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV172=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV173=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV174=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV175=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV176=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV177=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV178=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV179=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV180=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV181=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV182=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV183=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV184=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV185=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV186=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV187=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV188=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV189=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV190=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV191=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV192=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV193=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV194=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV195=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV196=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV197=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV198=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV199=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV200=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV201=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV202=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV203=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV204=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV205=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV206=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV207=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV208=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV209=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV210=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV211=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV212=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV213=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV214=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV215=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV216=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV217=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV218=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV219=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV220=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV221=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV222=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV223=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV224=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV225=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV226=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV227=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV228=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV229=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV230=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV231=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV232=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV233=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV234=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV235=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV236=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV237=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV238=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV239=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV240=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV241=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV242=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV243=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV244=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV245=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV246=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV247=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV248=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV249=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV250=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV251=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV252=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV253=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV254=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV255=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
ENV256=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(zend_test_zend_call_stack_get());
|
||||
|
||||
class Test1 {
|
||||
public function __destruct() {
|
||||
new Test1;
|
||||
}
|
||||
}
|
||||
|
||||
class Test2 {
|
||||
public function __clone() {
|
||||
clone $this;
|
||||
}
|
||||
}
|
||||
|
||||
function replace() {
|
||||
return preg_replace_callback('#.#', function () {
|
||||
return replace();
|
||||
}, 'x');
|
||||
}
|
||||
|
||||
try {
|
||||
new Test1;
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
clone new Test2;
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
replace();
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(4) {
|
||||
["base"]=>
|
||||
string(%d) "0x%x"
|
||||
["max_size"]=>
|
||||
string(%d) "0x%x"
|
||||
["position"]=>
|
||||
string(%d) "0x%x"
|
||||
["EG(stack_limit)"]=>
|
||||
string(%d) "0x%x"
|
||||
}
|
||||
Maximum call stack size of %d bytes reached. Infinite recursion?
|
||||
Maximum call stack size of %d bytes reached. Infinite recursion?
|
||||
Maximum call stack size of %d bytes reached. Infinite recursion?
|
41
Zend/tests/stack_limit/stack_limit_007.phpt
Normal file
41
Zend/tests/stack_limit/stack_limit_007.phpt
Normal file
|
@ -0,0 +1,41 @@
|
|||
--TEST--
|
||||
Stack limit 007 - Exception handling
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--INI--
|
||||
zend.max_allowed_stack_size=128K
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(zend_test_zend_call_stack_get());
|
||||
|
||||
function replace() {
|
||||
return preg_replace_callback('#.#', function () {
|
||||
try {
|
||||
$tryExecuted = true;
|
||||
return replace();
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
// We should not enter the catch block if we haven't executed at
|
||||
// least one op in the try block
|
||||
printf("Try executed: %d\n", $tryExecuted ?? 0);
|
||||
}
|
||||
}, 'x');
|
||||
}
|
||||
|
||||
replace();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(4) {
|
||||
["base"]=>
|
||||
string(%d) "0x%x"
|
||||
["max_size"]=>
|
||||
string(%d) "0x%x"
|
||||
["position"]=>
|
||||
string(%d) "0x%x"
|
||||
["EG(stack_limit)"]=>
|
||||
string(%d) "0x%x"
|
||||
}
|
||||
Maximum call stack size of %d bytes reached. Infinite recursion?
|
||||
Try executed: 1
|
54
Zend/tests/stack_limit/stack_limit_008.phpt
Normal file
54
Zend/tests/stack_limit/stack_limit_008.phpt
Normal file
|
@ -0,0 +1,54 @@
|
|||
--TEST--
|
||||
Stack limit 008 - Exception handling
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--INI--
|
||||
zend.max_allowed_stack_size=128K
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(zend_test_zend_call_stack_get());
|
||||
|
||||
function replace() {
|
||||
return preg_replace_callback('#.#', function () {
|
||||
try {
|
||||
return replace();
|
||||
} catch (Error $e) {
|
||||
echo "Will throw:\n";
|
||||
try {
|
||||
return replace2();
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
}
|
||||
}, 'x');
|
||||
}
|
||||
|
||||
function replace2() {
|
||||
return preg_replace_callback('#.#', function () {
|
||||
try {
|
||||
return '';
|
||||
} finally {
|
||||
// We should not enter the finally block if we haven't executed at
|
||||
// least one op in the try block
|
||||
echo "Finally block: This should not execute\n";
|
||||
}
|
||||
}, 'x');
|
||||
}
|
||||
|
||||
replace();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(4) {
|
||||
["base"]=>
|
||||
string(%d) "0x%x"
|
||||
["max_size"]=>
|
||||
string(%d) "0x%x"
|
||||
["position"]=>
|
||||
string(%d) "0x%x"
|
||||
["EG(stack_limit)"]=>
|
||||
string(%d) "0x%x"
|
||||
}
|
||||
Will throw:
|
||||
Maximum call stack size of %d bytes reached. Infinite recursion?
|
24
Zend/tests/stack_limit/stack_limit_009.phpt
Normal file
24
Zend/tests/stack_limit/stack_limit_009.phpt
Normal file
|
@ -0,0 +1,24 @@
|
|||
--TEST--
|
||||
Stack limit 009 - Check that we can actually use all the stack
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(zend_test_zend_call_stack_get());
|
||||
|
||||
var_dump(zend_test_zend_call_stack_use_all());
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(4) {
|
||||
["base"]=>
|
||||
string(%d) "0x%x"
|
||||
["max_size"]=>
|
||||
string(%d) "0x%x"
|
||||
["position"]=>
|
||||
string(%d) "0x%x"
|
||||
["EG(stack_limit)"]=>
|
||||
string(%d) "0x%x"
|
||||
}
|
||||
int(%d)
|
48
Zend/tests/stack_limit/stack_limit_010.phpt
Normal file
48
Zend/tests/stack_limit/stack_limit_010.phpt
Normal file
|
@ -0,0 +1,48 @@
|
|||
--TEST--
|
||||
Stack limit 010 - Check stack size detection against known defaults
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!getenv('STACK_LIMIT_DEFAULTS_CHECK')) { die('skip STACK_LIMIT_DEFAULTS_CHECK not set'); }
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$stack = zend_test_zend_call_stack_get();
|
||||
|
||||
var_dump($stack);
|
||||
|
||||
$expectedMaxSize = match(php_uname('s')) {
|
||||
'Darwin' => 8*1024*1024,
|
||||
'FreeBSD' => match(php_uname('m')) {
|
||||
'amd64' => 512*1024*1024 - 4096,
|
||||
'i386' => 64*1024*1024 - 4096,
|
||||
},
|
||||
'Linux' => match (getenv('GITHUB_ACTIONS')) {
|
||||
'true' => 16*1024*1024, // https://github.com/actions/runner-images/pull/3328
|
||||
default => 8*1024*1024,
|
||||
},
|
||||
'Windows NT' => 67108864 - 4*4096, // Set by sapi/cli/config.w32
|
||||
};
|
||||
|
||||
printf("Expected max_size: 0x%x\n", $expectedMaxSize);
|
||||
printf("Actual max_size: %s\n", $stack['max_size']);
|
||||
|
||||
var_dump($stack['max_size'] === sprintf('0x%x', $expectedMaxSize));
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(4) {
|
||||
["base"]=>
|
||||
string(%d) "0x%x"
|
||||
["max_size"]=>
|
||||
string(%d) "0x%x"
|
||||
["position"]=>
|
||||
string(%d) "0x%x"
|
||||
["EG(stack_limit)"]=>
|
||||
string(%d) "0x%x"
|
||||
}
|
||||
Expected max_size: 0x%x
|
||||
Actual max_size: 0x%x
|
||||
bool(true)
|
48
Zend/tests/stack_limit/stack_limit_011.phpt
Normal file
48
Zend/tests/stack_limit/stack_limit_011.phpt
Normal file
|
@ -0,0 +1,48 @@
|
|||
--TEST--
|
||||
Stack limit 011 - Stack limit exhaustion during unwinding
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--INI--
|
||||
zend.max_allowed_stack_size=128K
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(zend_test_zend_call_stack_get());
|
||||
|
||||
class Test1 {
|
||||
public function __destruct() {
|
||||
new Test1;
|
||||
}
|
||||
}
|
||||
|
||||
function replace() {
|
||||
return preg_replace_callback('#.#', function () {
|
||||
try {
|
||||
replace();
|
||||
} finally {
|
||||
new Test1();
|
||||
}
|
||||
}, 'x');
|
||||
}
|
||||
|
||||
try {
|
||||
replace();
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
echo 'Previous: ', $e->getPrevious()->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(4) {
|
||||
["base"]=>
|
||||
string(%d) "0x%x"
|
||||
["max_size"]=>
|
||||
string(%d) "0x%x"
|
||||
["position"]=>
|
||||
string(%d) "0x%x"
|
||||
["EG(stack_limit)"]=>
|
||||
string(%d) "0x%x"
|
||||
}
|
||||
Maximum call stack size of %d bytes reached. Infinite recursion?
|
||||
Previous: Maximum call stack size of %d bytes reached. Infinite recursion?
|
54
Zend/tests/stack_limit/stack_limit_012.inc
Normal file
54
Zend/tests/stack_limit/stack_limit_012.inc
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
$test
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
->f()->f()->f()->f()->f()->f()->f()->f()->f()->f()
|
||||
;
|
37
Zend/tests/stack_limit/stack_limit_012.phpt
Normal file
37
Zend/tests/stack_limit/stack_limit_012.phpt
Normal file
|
@ -0,0 +1,37 @@
|
|||
--TEST--
|
||||
Stack limit 012 - Stack limit exhaustion during unwinding
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--INI--
|
||||
zend.max_allowed_stack_size=128K
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(zend_test_zend_call_stack_get());
|
||||
|
||||
function replace() {
|
||||
return preg_replace_callback('#.#', function () {
|
||||
try {
|
||||
replace();
|
||||
} finally {
|
||||
require __DIR__ . '/stack_limit_012.inc';
|
||||
}
|
||||
}, 'x');
|
||||
}
|
||||
|
||||
replace();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(4) {
|
||||
["base"]=>
|
||||
string(%d) "0x%x"
|
||||
["max_size"]=>
|
||||
string(%d) "0x%x"
|
||||
["position"]=>
|
||||
string(%d) "0x%x"
|
||||
["EG(stack_limit)"]=>
|
||||
string(%d) "0x%x"
|
||||
}
|
||||
|
||||
Fatal error: Maximum call stack size of %d bytes reached during compilation. Try splitting expression in %s on line %d
|
66
Zend/zend.c
66
Zend/zend.c
|
@ -35,6 +35,7 @@
|
|||
#include "zend_attributes.h"
|
||||
#include "zend_observer.h"
|
||||
#include "zend_fibers.h"
|
||||
#include "zend_call_stack.h"
|
||||
#include "Optimizer/zend_optimizer.h"
|
||||
|
||||
static size_t global_map_ptr_last = 0;
|
||||
|
@ -173,6 +174,52 @@ static ZEND_INI_MH(OnSetExceptionStringParamMaxLen) /* {{{ */
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
static ZEND_INI_MH(OnUpdateMaxAllowedStackSize) /* {{{ */
|
||||
{
|
||||
zend_long size = zend_ini_parse_quantity_warn(new_value, entry->name);
|
||||
|
||||
if (size < ZEND_MAX_ALLOWED_STACK_SIZE_UNCHECKED) {
|
||||
zend_error(E_WARNING, "Invalid \"%s\" setting. Value must be >= %d, but got " ZEND_LONG_FMT,
|
||||
ZSTR_VAL(entry->name), ZEND_MAX_ALLOWED_STACK_SIZE_UNCHECKED, size);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
EG(max_allowed_stack_size) = size;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static ZEND_INI_MH(OnUpdateReservedStackSize) /* {{{ */
|
||||
{
|
||||
zend_ulong size = zend_ini_parse_uquantity_warn(new_value, entry->name);
|
||||
|
||||
/* Min value accounts for alloca, PCRE2 START_FRAMES_SIZE, and some buffer
|
||||
* for normal function calls.
|
||||
* We could reduce this on systems without alloca if we also add stack size
|
||||
* checks before pcre2_match(). */
|
||||
#ifdef ZEND_ALLOCA_MAX_SIZE
|
||||
zend_ulong min = ZEND_ALLOCA_MAX_SIZE + 16*1024;
|
||||
#else
|
||||
zend_ulong min = 32*1024;
|
||||
#endif
|
||||
|
||||
if (size == 0) {
|
||||
size = min;
|
||||
} else if (size < min) {
|
||||
zend_error(E_WARNING, "Invalid \"%s\" setting. Value must be >= " ZEND_ULONG_FMT ", but got " ZEND_ULONG_FMT "\n",
|
||||
ZSTR_VAL(entry->name), min, size);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
EG(reserved_stack_size) = size;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
#endif /* ZEND_CHECK_STACK_LIMIT */
|
||||
|
||||
static ZEND_INI_MH(OnUpdateFiberStackSize) /* {{{ */
|
||||
{
|
||||
if (new_value) {
|
||||
|
@ -203,6 +250,12 @@ ZEND_INI_BEGIN()
|
|||
STD_ZEND_INI_BOOLEAN("zend.exception_ignore_args", "0", ZEND_INI_ALL, OnUpdateBool, exception_ignore_args, zend_executor_globals, executor_globals)
|
||||
STD_ZEND_INI_ENTRY("zend.exception_string_param_max_len", "15", ZEND_INI_ALL, OnSetExceptionStringParamMaxLen, exception_string_param_max_len, zend_executor_globals, executor_globals)
|
||||
STD_ZEND_INI_ENTRY("fiber.stack_size", NULL, ZEND_INI_ALL, OnUpdateFiberStackSize, fiber_stack_size, zend_executor_globals, executor_globals)
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
/* The maximum allowed call stack size. 0: auto detect, -1: no limit. For fibers, this is fiber.stack_size. */
|
||||
STD_ZEND_INI_ENTRY("zend.max_allowed_stack_size", "0", ZEND_INI_SYSTEM, OnUpdateMaxAllowedStackSize, max_allowed_stack_size, zend_executor_globals, executor_globals)
|
||||
/* Substracted from the max allowed stack size, as a buffer, when checking for overflow. 0: auto detect. */
|
||||
STD_ZEND_INI_ENTRY("zend.reserved_stack_size", "0", ZEND_INI_SYSTEM, OnUpdateReservedStackSize, reserved_stack_size, zend_executor_globals, executor_globals)
|
||||
#endif
|
||||
|
||||
ZEND_INI_END()
|
||||
|
||||
|
@ -796,6 +849,10 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals) /* {{
|
|||
executor_globals->record_errors = false;
|
||||
executor_globals->num_errors = 0;
|
||||
executor_globals->errors = NULL;
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
executor_globals->stack_limit = (void*)0;
|
||||
executor_globals->stack_base = (void*)0;
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -817,6 +874,9 @@ static void zend_new_thread_end_handler(THREAD_T thread_id) /* {{{ */
|
|||
{
|
||||
zend_copy_ini_directives();
|
||||
zend_ini_refresh_caches(ZEND_INI_STAGE_STARTUP);
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
zend_call_stack_init();
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
|
@ -982,7 +1042,7 @@ void zend_startup(zend_utility_functions *utility_functions) /* {{{ */
|
|||
CG(map_ptr_base) = ZEND_MAP_PTR_BIASED_BASE(NULL);
|
||||
CG(map_ptr_size) = 0;
|
||||
CG(map_ptr_last) = 0;
|
||||
#endif
|
||||
#endif /* ZTS */
|
||||
EG(error_reporting) = E_ALL & ~E_NOTICE;
|
||||
|
||||
zend_interned_strings_init();
|
||||
|
@ -1077,6 +1137,10 @@ zend_result zend_post_startup(void) /* {{{ */
|
|||
global_map_ptr_last = CG(map_ptr_last);
|
||||
#endif
|
||||
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
zend_call_stack_init();
|
||||
#endif
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
|
457
Zend/zend_call_stack.c
Normal file
457
Zend/zend_call_stack.c
Normal file
|
@ -0,0 +1,457 @@
|
|||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.00 of the Zend license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.zend.com/license/2_00.txt. |
|
||||
| If you did not receive a copy of the Zend license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@zend.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Arnaud Le Blanc <arnaud.lb@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* Inspired from Chromium's stack_util.cc */
|
||||
|
||||
#include "zend.h"
|
||||
#include "zend_globals.h"
|
||||
#include "zend_portability.h"
|
||||
#include "zend_call_stack.h"
|
||||
#include <stdint.h>
|
||||
#ifdef ZEND_WIN32
|
||||
# include <processthreadsapi.h>
|
||||
# include <memoryapi.h>
|
||||
#else /* ZEND_WIN32 */
|
||||
# include <sys/resource.h>
|
||||
# ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
# endif
|
||||
# ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
#endif /* ZEND_WIN32 */
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
# include <pthread_np.h>
|
||||
# include <sys/mman.h>
|
||||
# include <sys/sysctl.h>
|
||||
# include <sys/user.h>
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
|
||||
/* Called once per process or thread */
|
||||
ZEND_API void zend_call_stack_init(void) {
|
||||
if (!zend_call_stack_get(&EG(call_stack))) {
|
||||
EG(call_stack) = (zend_call_stack){0};
|
||||
}
|
||||
|
||||
switch (EG(max_allowed_stack_size)) {
|
||||
case ZEND_MAX_ALLOWED_STACK_SIZE_DETECT: {
|
||||
void *base = EG(call_stack).base;
|
||||
size_t size = EG(call_stack).max_size;
|
||||
if (UNEXPECTED(base == (void*)0)) {
|
||||
base = zend_call_stack_position();
|
||||
size = zend_call_stack_default_size();
|
||||
/* base is not the actual stack base */
|
||||
size -= 32 * 1024;
|
||||
}
|
||||
EG(stack_base) = base;
|
||||
EG(stack_limit) = zend_call_stack_limit(base, size, EG(reserved_stack_size));
|
||||
break;
|
||||
}
|
||||
case ZEND_MAX_ALLOWED_STACK_SIZE_UNCHECKED: {
|
||||
EG(stack_base) = (void*)0;
|
||||
EG(stack_limit) = (void*)0;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
ZEND_ASSERT(EG(max_allowed_stack_size) > 0);
|
||||
void *base = EG(call_stack).base;
|
||||
if (UNEXPECTED(base == (void*)0)) {
|
||||
base = zend_call_stack_position();
|
||||
}
|
||||
EG(stack_base) = base;
|
||||
EG(stack_limit) = zend_call_stack_limit(base, EG(max_allowed_stack_size), EG(reserved_stack_size));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
static bool zend_call_stack_is_main_thread(void) {
|
||||
# ifdef HAVE_GETTID
|
||||
return getpid() == gettid();
|
||||
# else
|
||||
return getpid() == syscall(SYS_gettid);
|
||||
# endif
|
||||
}
|
||||
|
||||
# ifdef HAVE_PTHREAD_GETATTR_NP
|
||||
static bool zend_call_stack_get_linux_pthread(zend_call_stack *stack)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
int error;
|
||||
void *addr;
|
||||
size_t max_size;
|
||||
|
||||
/* pthread_getattr_np() will return bogus values for the main thread with
|
||||
* musl or with some old glibc versions */
|
||||
ZEND_ASSERT(!zend_call_stack_is_main_thread());
|
||||
|
||||
error = pthread_getattr_np(pthread_self(), &attr);
|
||||
if (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
error = pthread_attr_getstack(&attr, &addr, &max_size);
|
||||
if (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
# if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 8))
|
||||
{
|
||||
size_t guard_size;
|
||||
/* In glibc prior to 2.8, addr and size include the guard pages */
|
||||
error = pthread_attr_getguardsize(&attr, &guard_size);
|
||||
if (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
addr = (int8_t*)addr + guard_size;
|
||||
max_size -= guard_size;
|
||||
}
|
||||
# endif /* glibc < 2.8 */
|
||||
|
||||
stack->base = (int8_t*)addr + max_size;
|
||||
stack->max_size = max_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
# else /* HAVE_PTHREAD_GETATTR_NP */
|
||||
static bool zend_call_stack_get_linux_pthread(zend_call_stack *stack)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
# endif /* HAVE_PTHREAD_GETATTR_NP */
|
||||
|
||||
static bool zend_call_stack_get_linux_proc_maps(zend_call_stack *stack)
|
||||
{
|
||||
FILE *f;
|
||||
char buffer[4096];
|
||||
uintptr_t addr_on_stack = (uintptr_t)&buffer;
|
||||
uintptr_t start, end, prev_end = 0;
|
||||
size_t max_size;
|
||||
bool found = false;
|
||||
struct rlimit rlim;
|
||||
int error;
|
||||
|
||||
/* This method is relevant only for the main thread */
|
||||
ZEND_ASSERT(zend_call_stack_is_main_thread());
|
||||
|
||||
/* Scan the process memory mappings to find the one containing the stack.
|
||||
*
|
||||
* The end of the stack mapping is the base of the stack. The start is
|
||||
* adjusted by the kernel as the stack grows. The maximum stack size is
|
||||
* determined by RLIMIT_STACK and the previous mapping.
|
||||
*
|
||||
*
|
||||
* ^ Higher addresses ^
|
||||
* : :
|
||||
* : :
|
||||
* Mapping end --> |-------------------| <-- Stack base (stack start)
|
||||
* | | ^
|
||||
* | Stack Mapping | | Stack size
|
||||
* | | v
|
||||
* Mapping start --> |-------------------| <-- Current stack end
|
||||
* (adjusted : :
|
||||
* downwards as the . .
|
||||
* stack grows) : :
|
||||
* |-------------------|
|
||||
* | Some Mapping | The previous mapping may prevent
|
||||
* |-------------------| stack growth
|
||||
* : :
|
||||
* : :
|
||||
* v Lower addresses v
|
||||
*/
|
||||
|
||||
f = fopen("/proc/self/maps", "r");
|
||||
if (!f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), f) && sscanf(buffer, "%" SCNxPTR "-%" SCNxPTR, &start, &end) == 2) {
|
||||
if (start <= addr_on_stack && end >= addr_on_stack) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
prev_end = end;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
|
||||
error = getrlimit(RLIMIT_STACK, &rlim);
|
||||
if (error || rlim.rlim_cur == RLIM_INFINITY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
max_size = rlim.rlim_cur;
|
||||
|
||||
/* Previous mapping may prevent the stack from growing */
|
||||
if (end - max_size < prev_end) {
|
||||
max_size = prev_end - end;
|
||||
}
|
||||
|
||||
stack->base = (void*)end;
|
||||
stack->max_size = max_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool zend_call_stack_get_linux(zend_call_stack *stack)
|
||||
{
|
||||
if (zend_call_stack_is_main_thread()) {
|
||||
return zend_call_stack_get_linux_proc_maps(stack);
|
||||
}
|
||||
|
||||
return zend_call_stack_get_linux_pthread(stack);
|
||||
}
|
||||
#else /* __linux__ */
|
||||
static bool zend_call_stack_get_linux(zend_call_stack *stack)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
static bool zend_call_stack_is_main_thread(void)
|
||||
{
|
||||
int is_main = pthread_main_np();
|
||||
return is_main == -1 || is_main == 1;
|
||||
}
|
||||
|
||||
# if defined(HAVE_PTHREAD_ATTR_GET_NP) && defined(HAVE_PTHREAD_ATTR_GET_STACK)
|
||||
static bool zend_call_stack_get_freebsd_pthread(zend_call_stack *stack)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
int error;
|
||||
void *addr;
|
||||
size_t max_size;
|
||||
size_t guard_size;
|
||||
|
||||
/* pthread will return bogus values for the main thread */
|
||||
ZEND_ASSERT(!zend_call_stack_is_main_thread());
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
|
||||
error = pthread_attr_get_np(pthread_self(), &attr);
|
||||
if (error) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
error = pthread_attr_getstack(&attr, &addr, &max_size);
|
||||
if (error) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
stack->base = (int8_t*)addr + max_size;
|
||||
stack->max_size = max_size;
|
||||
|
||||
pthread_attr_destroy(&attr);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
pthread_attr_destroy(&attr);
|
||||
return false;
|
||||
}
|
||||
# else /* defined(HAVE_PTHREAD_ATTR_GET_NP) && defined(HAVE_PTHREAD_ATTR_GET_STACK) */
|
||||
static bool zend_call_stack_get_freebsd_pthread(zend_call_stack *stack)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
# endif /* defined(HAVE_PTHREAD_ATTR_GET_NP) && defined(HAVE_PTHREAD_ATTR_GET_STACK) */
|
||||
|
||||
static bool zend_call_stack_get_freebsd_sysctl(zend_call_stack *stack)
|
||||
{
|
||||
void *stack_base;
|
||||
int mib[2] = {CTL_KERN, KERN_USRSTACK};
|
||||
size_t len = sizeof(stack_base);
|
||||
struct rlimit rlim;
|
||||
|
||||
/* This method is relevant only for the main thread */
|
||||
ZEND_ASSERT(zend_call_stack_is_main_thread());
|
||||
|
||||
if (sysctl(mib, sizeof(mib)/sizeof(*mib), &stack_base, &len, NULL, 0) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getrlimit(RLIMIT_STACK, &rlim) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rlim.rlim_cur == RLIM_INFINITY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t guard_size = getpagesize();
|
||||
|
||||
stack->base = stack_base;
|
||||
stack->max_size = rlim.rlim_cur - guard_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool zend_call_stack_get_freebsd(zend_call_stack *stack)
|
||||
{
|
||||
if (zend_call_stack_is_main_thread()) {
|
||||
return zend_call_stack_get_freebsd_sysctl(stack);
|
||||
}
|
||||
|
||||
return zend_call_stack_get_freebsd_pthread(stack);
|
||||
}
|
||||
#else
|
||||
static bool zend_call_stack_get_freebsd(zend_call_stack *stack)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
#ifdef ZEND_WIN32
|
||||
static bool zend_call_stack_get_win32(zend_call_stack *stack)
|
||||
{
|
||||
ULONG_PTR low_limit, high_limit;
|
||||
ULONG size;
|
||||
MEMORY_BASIC_INFORMATION guard_region = {0}, uncommitted_region = {0};
|
||||
size_t result_size, page_size;
|
||||
|
||||
/* The stack consists of three regions: committed, guard, and uncommitted.
|
||||
* Memory is committed when the guard region is accessed. If only one page
|
||||
* is left in the uncommitted region, a stack overflow error is raised
|
||||
* instead.
|
||||
*
|
||||
* The total useable stack size is the size of the committed and uncommitted
|
||||
* regions less one page.
|
||||
*
|
||||
* http://blogs.msdn.com/b/satyem/archive/2012/08/13/thread-s-stack-memory-management.aspx
|
||||
* https://learn.microsoft.com/en-us/windows/win32/procthread/thread-stack-size
|
||||
*
|
||||
* ^ Higher addresses ^
|
||||
* : :
|
||||
* : :
|
||||
* high_limit --> |--------------------|
|
||||
* ^ | |
|
||||
* | | Committed region |
|
||||
* | | |
|
||||
* | |------------------- | <-- guard_region.BaseAddress
|
||||
* reserved | | | + guard_region.RegionSize
|
||||
* size | | Guard region |
|
||||
* | | |
|
||||
* | |--------------------| <-- guard_region.BaseAddress,
|
||||
* | | | uncommitted_region.BaseAddress
|
||||
* | | Uncommitted region | + uncommitted_region.RegionSize
|
||||
* v | |
|
||||
* low_limit --> |------------------- | <-- uncommitted_region.BaseAddress
|
||||
* : :
|
||||
* : :
|
||||
* v Lower addresses v
|
||||
*/
|
||||
|
||||
GetCurrentThreadStackLimits(&low_limit, &high_limit);
|
||||
|
||||
result_size = VirtualQuery((void*)low_limit,
|
||||
&uncommitted_region, sizeof(uncommitted_region));
|
||||
ZEND_ASSERT(result_size >= sizeof(uncommitted_region));
|
||||
|
||||
result_size = VirtualQuery((int8_t*)uncommitted_region.BaseAddress + uncommitted_region.RegionSize,
|
||||
&guard_region, sizeof(guard_region));
|
||||
ZEND_ASSERT(result_size >= sizeof(uncommitted_region));
|
||||
|
||||
stack->base = (void*)high_limit;
|
||||
stack->max_size = (uintptr_t)high_limit - (uintptr_t)low_limit;
|
||||
|
||||
ZEND_ASSERT(stack->max_size > guard_region.RegionSize);
|
||||
stack->max_size -= guard_region.RegionSize;
|
||||
|
||||
/* The uncommitted region does not shrink below 1 page */
|
||||
page_size = zend_get_page_size();
|
||||
ZEND_ASSERT(stack->max_size > page_size);
|
||||
stack->max_size -= page_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
#else /* ZEND_WIN32 */
|
||||
static bool zend_call_stack_get_win32(zend_call_stack *stack)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* ZEND_WIN32 */
|
||||
|
||||
#if defined(__APPLE__) && defined(HAVE_PTHREAD_GET_STACKADDR_NP)
|
||||
static bool zend_call_stack_get_macos(zend_call_stack *stack)
|
||||
{
|
||||
void *base = pthread_get_stackaddr_np(pthread_self());
|
||||
size_t max_size;
|
||||
|
||||
if (pthread_main_np()) {
|
||||
/* pthread_get_stacksize_np() returns a too low value for the main
|
||||
* thread in OSX 10.9, 10.10:
|
||||
* https://mail.openjdk.org/pipermail/hotspot-dev/2013-October/011353.html
|
||||
* https://github.com/rust-lang/rust/issues/43347
|
||||
*/
|
||||
|
||||
/* Stack size is 8MiB by default for main threads
|
||||
* https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html */
|
||||
max_size = 8 * 1024 * 1024;
|
||||
} else {
|
||||
max_size = pthread_get_stacksize_np(pthread_self());
|
||||
}
|
||||
|
||||
stack->base = base;
|
||||
stack->max_size = max_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
#else /* defined(__APPLE__) && defined(HAVE_PTHREAD_GET_STACKADDR_NP) */
|
||||
static bool zend_call_stack_get_macos(zend_call_stack *stack)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* defined(__APPLE__) && defined(HAVE_PTHREAD_GET_STACKADDR_NP) */
|
||||
|
||||
/** Get the stack information for the calling thread */
|
||||
ZEND_API bool zend_call_stack_get(zend_call_stack *stack)
|
||||
{
|
||||
if (zend_call_stack_get_linux(stack)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (zend_call_stack_get_freebsd(stack)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (zend_call_stack_get_win32(stack)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (zend_call_stack_get_macos(stack)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* ZEND_CHECK_STACK_LIMIT */
|
91
Zend/zend_call_stack.h
Normal file
91
Zend/zend_call_stack.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.00 of the Zend license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.zend.com/license/2_00.txt. |
|
||||
| If you did not receive a copy of the Zend license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@zend.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Arnaud Le Blanc <arnaud.lb@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef ZEND_CALL_STACK_H
|
||||
#define ZEND_CALL_STACK_H
|
||||
|
||||
#include "zend.h"
|
||||
#include "zend_portability.h"
|
||||
#ifdef __APPLE__
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
|
||||
typedef struct _zend_call_stack {
|
||||
void *base;
|
||||
size_t max_size;
|
||||
} zend_call_stack;
|
||||
|
||||
ZEND_API void zend_call_stack_init(void);
|
||||
|
||||
ZEND_API bool zend_call_stack_get(zend_call_stack *stack);
|
||||
|
||||
/** Returns an approximation of the current stack position */
|
||||
static zend_always_inline void *zend_call_stack_position(void) {
|
||||
#ifdef ZEND_WIN32
|
||||
return _AddressOfReturnAddress();
|
||||
#elif HAVE_BUILTIN_FRAME_ADDRESS
|
||||
return __builtin_frame_address(0);
|
||||
#else
|
||||
void *a;
|
||||
void *pos = (void*)&a;
|
||||
return pos;
|
||||
#endif
|
||||
}
|
||||
|
||||
static zend_always_inline bool zend_call_stack_overflowed(void *stack_limit) {
|
||||
return (uintptr_t) zend_call_stack_position() <= (uintptr_t) stack_limit;
|
||||
}
|
||||
|
||||
static inline void* zend_call_stack_limit(void *base, size_t size, size_t reserved_size)
|
||||
{
|
||||
if (UNEXPECTED(size > (uintptr_t)base)) {
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
base = (int8_t*)base - size;
|
||||
|
||||
if (UNEXPECTED(UINTPTR_MAX - (uintptr_t)base < reserved_size)) {
|
||||
return (void*)UINTPTR_MAX;
|
||||
}
|
||||
|
||||
return (int8_t*)base + reserved_size;
|
||||
}
|
||||
|
||||
static inline size_t zend_call_stack_default_size(void)
|
||||
{
|
||||
#ifdef __linux__
|
||||
return 8 * 1024 * 1024;
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
return 8 * 1024 * 1024;
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html
|
||||
if (pthread_main_np()) {
|
||||
return 8 * 1024 * 1024;
|
||||
}
|
||||
return 512 * 1024;
|
||||
#endif
|
||||
|
||||
return 2 * 1024 * 1024;
|
||||
}
|
||||
|
||||
#endif /* ZEND_CHECK_STACK_LIMIT */
|
||||
#endif /* ZEND_CALL_STACK_H */
|
|
@ -34,6 +34,7 @@
|
|||
#include "zend_vm.h"
|
||||
#include "zend_enum.h"
|
||||
#include "zend_observer.h"
|
||||
#include "zend_call_stack.h"
|
||||
|
||||
#define SET_NODE(target, src) do { \
|
||||
target ## _type = (src)->op_type; \
|
||||
|
@ -10425,6 +10426,14 @@ static void zend_compile_expr_inner(znode *result, zend_ast *ast) /* {{{ */
|
|||
|
||||
static void zend_compile_expr(znode *result, zend_ast *ast)
|
||||
{
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR,
|
||||
"Maximum call stack size of %zu bytes reached during compilation. Try splitting expression",
|
||||
(size_t) ((uintptr_t) EG(stack_base) - (uintptr_t) EG(stack_limit)));
|
||||
}
|
||||
#endif /* ZEND_CHECK_STACK_LIMIT */
|
||||
|
||||
uint32_t checkpoint = zend_short_circuiting_checkpoint();
|
||||
zend_compile_expr_inner(result, ast);
|
||||
zend_short_circuiting_commit(checkpoint, result, ast);
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "zend_smart_str.h"
|
||||
#include "zend_observer.h"
|
||||
#include "zend_system_id.h"
|
||||
#include "zend_call_stack.h"
|
||||
#include "Optimizer/zend_func_info.h"
|
||||
|
||||
/* Virtual current working directory support */
|
||||
|
@ -2228,6 +2229,14 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_new_element_for_s
|
|||
zend_throw_error(NULL, "[] operator not supported for strings");
|
||||
}
|
||||
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_call_stack_size_error(void)
|
||||
{
|
||||
zend_throw_error(NULL, "Maximum call stack size of %zu bytes reached. Infinite recursion?",
|
||||
(size_t) ((uintptr_t) EG(stack_base) - (uintptr_t) EG(stack_limit)));
|
||||
}
|
||||
#endif /* ZEND_CHECK_STACK_LIMIT */
|
||||
|
||||
static ZEND_COLD void zend_binary_assign_op_dim_slow(zval *container, zval *dim OPLINE_DC EXECUTE_DATA_DC)
|
||||
{
|
||||
if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "zend_weakrefs.h"
|
||||
#include "zend_inheritance.h"
|
||||
#include "zend_observer.h"
|
||||
#include "zend_call_stack.h"
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
|
|
@ -108,6 +108,10 @@ typedef struct _zend_fiber_vm_state {
|
|||
uint32_t jit_trace_num;
|
||||
JMP_BUF *bailout;
|
||||
zend_fiber *active_fiber;
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
void *stack_base;
|
||||
void *stack_limit;
|
||||
#endif
|
||||
} zend_fiber_vm_state;
|
||||
|
||||
static zend_always_inline void zend_fiber_capture_vm_state(zend_fiber_vm_state *state)
|
||||
|
@ -121,6 +125,10 @@ static zend_always_inline void zend_fiber_capture_vm_state(zend_fiber_vm_state *
|
|||
state->jit_trace_num = EG(jit_trace_num);
|
||||
state->bailout = EG(bailout);
|
||||
state->active_fiber = EG(active_fiber);
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
state->stack_base = EG(stack_base);
|
||||
state->stack_limit = EG(stack_limit);
|
||||
#endif
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_fiber_restore_vm_state(zend_fiber_vm_state *state)
|
||||
|
@ -134,6 +142,10 @@ static zend_always_inline void zend_fiber_restore_vm_state(zend_fiber_vm_state *
|
|||
EG(jit_trace_num) = state->jit_trace_num;
|
||||
EG(bailout) = state->bailout;
|
||||
EG(active_fiber) = state->active_fiber;
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
EG(stack_base) = state->stack_base;
|
||||
EG(stack_limit) = state->stack_limit;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ZEND_FIBER_UCONTEXT
|
||||
|
@ -294,6 +306,31 @@ static void zend_fiber_stack_free(zend_fiber_stack *stack)
|
|||
|
||||
efree(stack);
|
||||
}
|
||||
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
ZEND_API void* zend_fiber_stack_limit(zend_fiber_stack *stack)
|
||||
{
|
||||
zend_ulong reserve = EG(reserved_stack_size);
|
||||
|
||||
#ifdef __APPLE__
|
||||
/* On Apple Clang, the stack probing function ___chkstk_darwin incorrectly
|
||||
* probes a location that is twice the entered function's stack usage away
|
||||
* from the stack pointer, when using an alternative stack.
|
||||
* https://openradar.appspot.com/radar?id=5497722702397440
|
||||
*/
|
||||
reserve = reserve * 2;
|
||||
#endif
|
||||
|
||||
/* stack->pointer is the end of the stack */
|
||||
return (int8_t*)stack->pointer + reserve;
|
||||
}
|
||||
|
||||
ZEND_API void* zend_fiber_stack_base(zend_fiber_stack *stack)
|
||||
{
|
||||
return (void*)((uintptr_t)stack->pointer + stack->size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ZEND_FIBER_UCONTEXT
|
||||
static ZEND_NORETURN void zend_fiber_trampoline(void)
|
||||
#else
|
||||
|
@ -535,6 +572,11 @@ static ZEND_STACK_ALIGNED void zend_fiber_execute(zend_fiber_transfer *transfer)
|
|||
EG(jit_trace_num) = 0;
|
||||
EG(error_reporting) = error_reporting;
|
||||
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
EG(stack_base) = zend_fiber_stack_base(fiber->context.stack);
|
||||
EG(stack_limit) = zend_fiber_stack_limit(fiber->context.stack);
|
||||
#endif
|
||||
|
||||
fiber->fci.retval = &fiber->result;
|
||||
|
||||
zend_call_function(&fiber->fci, &fiber->fci_cache);
|
||||
|
|
|
@ -136,6 +136,10 @@ struct _zend_fiber {
|
|||
ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, void *kind, zend_fiber_coroutine coroutine, size_t stack_size);
|
||||
ZEND_API void zend_fiber_destroy_context(zend_fiber_context *context);
|
||||
ZEND_API void zend_fiber_switch_context(zend_fiber_transfer *transfer);
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
ZEND_API void* zend_fiber_stack_limit(zend_fiber_stack *stack);
|
||||
ZEND_API void* zend_fiber_stack_base(zend_fiber_stack *stack);
|
||||
#endif /* ZEND_CHECK_STACK_LIMIT */
|
||||
|
||||
ZEND_API void zend_fiber_switch_block(void);
|
||||
ZEND_API void zend_fiber_switch_unblock(void);
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "zend_multibyte.h"
|
||||
#include "zend_multiply.h"
|
||||
#include "zend_arena.h"
|
||||
#include "zend_call_stack.h"
|
||||
|
||||
/* Define ZTS if you want a thread-safe Zend */
|
||||
/*#undef ZTS*/
|
||||
|
@ -54,6 +55,10 @@ END_EXTERN_C()
|
|||
|
||||
#define SYMTABLE_CACHE_SIZE 32
|
||||
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
# define ZEND_MAX_ALLOWED_STACK_SIZE_UNCHECKED -1
|
||||
# define ZEND_MAX_ALLOWED_STACK_SIZE_DETECT 0
|
||||
#endif
|
||||
|
||||
#include "zend_compile.h"
|
||||
|
||||
|
@ -193,6 +198,8 @@ struct _zend_executor_globals {
|
|||
zend_atomic_bool vm_interrupt;
|
||||
zend_atomic_bool timed_out;
|
||||
zend_long hard_timeout;
|
||||
void *stack_base;
|
||||
void *stack_limit;
|
||||
|
||||
#ifdef ZEND_WIN32
|
||||
OSVERSIONINFOEX windows_version_info;
|
||||
|
@ -271,6 +278,12 @@ struct _zend_executor_globals {
|
|||
zend_string *filename_override;
|
||||
zend_long lineno_override;
|
||||
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
zend_call_stack call_stack;
|
||||
zend_long max_allowed_stack_size;
|
||||
zend_ulong reserved_stack_size;
|
||||
#endif
|
||||
|
||||
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
|
||||
};
|
||||
|
||||
|
|
|
@ -7928,6 +7928,12 @@ ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_ca
|
|||
ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
|
||||
{
|
||||
const zend_op *throw_op = EG(opline_before_exception);
|
||||
|
||||
/* Exception was thrown before executing any op */
|
||||
if (UNEXPECTED(!throw_op)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper, try_catch_offset, -1, 0, 0);
|
||||
}
|
||||
|
||||
uint32_t throw_op_num = throw_op - EX(func)->op_array.opcodes;
|
||||
int i, current_try_catch_offset = -1;
|
||||
|
||||
|
|
16
Zend/zend_vm_execute.h
generated
16
Zend/zend_vm_execute.h
generated
|
@ -3181,6 +3181,12 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try
|
|||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
const zend_op *throw_op = EG(opline_before_exception);
|
||||
|
||||
/* Exception was thrown before executing any op */
|
||||
if (UNEXPECTED(!throw_op)) {
|
||||
ZEND_VM_TAIL_CALL(zend_dispatch_try_catch_finally_helper_SPEC(-1, 0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
|
||||
}
|
||||
|
||||
uint32_t throw_op_num = throw_op - EX(func)->op_array.opcodes;
|
||||
int i, current_try_catch_offset = -1;
|
||||
|
||||
|
@ -55774,6 +55780,16 @@ ZEND_API void execute_ex(zend_execute_data *ex)
|
|||
LOAD_OPLINE();
|
||||
ZEND_VM_LOOP_INTERRUPT_CHECK();
|
||||
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) {
|
||||
zend_call_stack_size_error();
|
||||
/* No opline was executed before exception */
|
||||
EG(opline_before_exception) = NULL;
|
||||
LOAD_OPLINE();
|
||||
/* Fall through to handle exception below. */
|
||||
}
|
||||
#endif /* ZEND_CHECK_STACK_LIMIT */
|
||||
|
||||
while (1) {
|
||||
#if !defined(ZEND_VM_FP_GLOBAL_REG) || !defined(ZEND_VM_IP_GLOBAL_REG)
|
||||
int ret;
|
||||
|
|
|
@ -16,6 +16,16 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *ex)
|
|||
LOAD_OPLINE();
|
||||
ZEND_VM_LOOP_INTERRUPT_CHECK();
|
||||
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) {
|
||||
zend_call_stack_size_error();
|
||||
/* No opline was executed before exception */
|
||||
EG(opline_before_exception) = NULL;
|
||||
LOAD_OPLINE();
|
||||
/* Fall through to handle exception below. */
|
||||
}
|
||||
#endif /* ZEND_CHECK_STACK_LIMIT */
|
||||
|
||||
while (1) {
|
||||
{%ZEND_VM_CONTINUE_LABEL%}
|
||||
{%ZEND_VM_DISPATCH%} {
|
||||
|
|
20
build/php.m4
20
build/php.m4
|
@ -2733,6 +2733,26 @@ AC_DEFUN([PHP_CHECK_BUILTIN_CPU_SUPPORTS], [
|
|||
[$have_builtin_cpu_supports], [Whether the compiler supports __builtin_cpu_supports])
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl PHP_CHECK_BUILTIN_FRAME_ADDRESS
|
||||
dnl
|
||||
AC_DEFUN([PHP_CHECK_BUILTIN_FRAME_ADDRESS], [
|
||||
AC_MSG_CHECKING([for __builtin_frame_address])
|
||||
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [[
|
||||
return __builtin_frame_address(0) != (void*)0;
|
||||
]])], [
|
||||
have_builtin_frame_address=1
|
||||
AC_MSG_RESULT([yes])
|
||||
], [
|
||||
have_builtin_frame_address=0
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
|
||||
AC_DEFINE_UNQUOTED([PHP_HAVE_BUILTIN_FRAME_ADDRESS],
|
||||
[$have_builtin_frame_address], [Whether the compiler supports __builtin_frame_address])
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl PHP_PATCH_CONFIG_HEADERS([FILE])
|
||||
dnl
|
||||
|
|
|
@ -510,6 +510,8 @@ dnl Check __builtin_cpu_init
|
|||
PHP_CHECK_BUILTIN_CPU_INIT
|
||||
dnl Check __builtin_cpu_supports
|
||||
PHP_CHECK_BUILTIN_CPU_SUPPORTS
|
||||
dnl Check __builtin_frame_address
|
||||
PHP_CHECK_BUILTIN_FRAME_ADDRESS
|
||||
dnl Check prctl
|
||||
PHP_CHECK_PRCTL
|
||||
dnl Check procctl
|
||||
|
@ -1701,7 +1703,7 @@ PHP_ADD_SOURCES_X(/main, internal_functions_cli.c, -DZEND_ENABLE_STATIC_TSRMLS_C
|
|||
PHP_ADD_SOURCES(Zend, \
|
||||
zend_language_parser.c zend_language_scanner.c \
|
||||
zend_ini_parser.c zend_ini_scanner.c \
|
||||
zend_alloc.c zend_compile.c zend_constants.c zend_dtrace.c \
|
||||
zend_alloc.c zend_call_stack.c zend_compile.c zend_constants.c zend_dtrace.c \
|
||||
zend_execute_API.c zend_highlight.c zend_llist.c \
|
||||
zend_vm_opcodes.c zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \
|
||||
zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
static ZEND_COLD void undef_result_after_exception(void) {
|
||||
const zend_op *opline = EG(opline_before_exception);
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (opline->result_type & (IS_VAR | IS_TMP_VAR)) {
|
||||
if (opline && opline->result_type & (IS_VAR | IS_TMP_VAR)) {
|
||||
zend_execute_data *execute_data = EG(current_execute_data);
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
}
|
||||
|
@ -785,7 +785,7 @@ static zval* ZEND_FASTCALL zend_jit_fetch_dim_rw_helper(zend_array *ht, zval *di
|
|||
if (UNEXPECTED(opline->opcode == ZEND_HANDLE_EXCEPTION)) {
|
||||
opline = EG(opline_before_exception);
|
||||
}
|
||||
if (!zend_jit_undefined_op_helper_write(ht, opline->op2.var)) {
|
||||
if (opline && !zend_jit_undefined_op_helper_write(ht, opline->op2.var)) {
|
||||
if (opline->result_type & (IS_VAR | IS_TMP_VAR)) {
|
||||
if (EG(exception)) {
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
|
@ -1003,7 +1003,8 @@ static zval* ZEND_FASTCALL zend_jit_fetch_dim_w_helper(zend_array *ht, zval *dim
|
|||
default:
|
||||
zend_jit_illegal_offset();
|
||||
undef_result_after_exception();
|
||||
if ((EG(opline_before_exception)+1)->opcode == ZEND_OP_DATA
|
||||
if (EG(opline_before_exception)
|
||||
&& (EG(opline_before_exception)+1)->opcode == ZEND_OP_DATA
|
||||
&& ((EG(opline_before_exception)+1)->op1_type & (IS_VAR|IS_TMP_VAR))) {
|
||||
zend_execute_data *execute_data = EG(current_execute_data);
|
||||
|
||||
|
|
|
@ -183,7 +183,7 @@ bool ZEND_FASTCALL zend_jit_deprecated_helper(OPLINE_D)
|
|||
zend_execute_data *execute_data = EG(current_execute_data);
|
||||
#endif
|
||||
const zend_op *opline = EG(opline_before_exception);
|
||||
if (RETURN_VALUE_USED(opline)) {
|
||||
if (opline && RETURN_VALUE_USED(opline)) {
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
}
|
||||
|
||||
|
|
|
@ -95,6 +95,10 @@ static ZEND_STACK_ALIGNED void zend_test_fiber_execute(zend_fiber_transfer *tran
|
|||
EG(current_execute_data) = execute_data;
|
||||
EG(jit_trace_num) = 0;
|
||||
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
EG(stack_base) = zend_fiber_stack_base(fiber->context.stack);
|
||||
EG(stack_limit) = zend_fiber_stack_limit(fiber->context.stack);
|
||||
#endif
|
||||
fiber->fci.retval = &retval;
|
||||
|
||||
zend_call_function(&fiber->fci, &fiber->fci_cache);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "zend_weakrefs.h"
|
||||
#include "Zend/Optimizer/zend_optimizer.h"
|
||||
#include "test_arginfo.h"
|
||||
#include "zend_call_stack.h"
|
||||
|
||||
ZEND_DECLARE_MODULE_GLOBALS(zend_test)
|
||||
|
||||
|
@ -456,6 +457,65 @@ static ZEND_FUNCTION(zend_test_parameter_with_attribute)
|
|||
RETURN_LONG(1);
|
||||
}
|
||||
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
static ZEND_FUNCTION(zend_test_zend_call_stack_get)
|
||||
{
|
||||
zend_call_stack stack;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_NONE();
|
||||
|
||||
if (zend_call_stack_get(&stack)) {
|
||||
zend_string *str;
|
||||
|
||||
array_init(return_value);
|
||||
|
||||
str = strpprintf(0, "%p", stack.base);
|
||||
add_assoc_str(return_value, "base", str);
|
||||
|
||||
str = strpprintf(0, "0x%zx", stack.max_size);
|
||||
add_assoc_str(return_value, "max_size", str);
|
||||
|
||||
str = strpprintf(0, "%p", zend_call_stack_position());
|
||||
add_assoc_str(return_value, "position", str);
|
||||
|
||||
str = strpprintf(0, "%p", EG(stack_limit));
|
||||
add_assoc_str(return_value, "EG(stack_limit)", str);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
zend_long (*volatile zend_call_stack_use_all_fun)(void *limit);
|
||||
|
||||
static zend_long zend_call_stack_use_all(void *limit)
|
||||
{
|
||||
if (zend_call_stack_overflowed(limit)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1 + zend_call_stack_use_all_fun(limit);
|
||||
}
|
||||
|
||||
static ZEND_FUNCTION(zend_test_zend_call_stack_use_all)
|
||||
{
|
||||
zend_call_stack stack;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_NONE();
|
||||
|
||||
if (!zend_call_stack_get(&stack)) {
|
||||
return;
|
||||
}
|
||||
|
||||
zend_call_stack_use_all_fun = zend_call_stack_use_all;
|
||||
|
||||
void *limit = zend_call_stack_limit(stack.base, stack.max_size, 4096);
|
||||
|
||||
RETURN_LONG(zend_call_stack_use_all(limit));
|
||||
}
|
||||
#endif /* ZEND_CHECK_STACK_LIMIT */
|
||||
|
||||
static zend_object *zend_test_class_new(zend_class_entry *class_type)
|
||||
{
|
||||
zend_object *obj = zend_objects_new(class_type);
|
||||
|
|
|
@ -161,6 +161,11 @@ namespace {
|
|||
function zend_test_zend_ini_parse_uquantity(string $str): int {}
|
||||
|
||||
function zend_test_zend_ini_str(): string {}
|
||||
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
function zend_test_zend_call_stack_get(): ?array {}
|
||||
function zend_test_zend_call_stack_use_all(): int {}
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace ZendTestNS {
|
||||
|
|
24
ext/zend_test/test_arginfo.h
generated
24
ext/zend_test/test_arginfo.h
generated
|
@ -1,5 +1,5 @@
|
|||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 786b35a1fbff38215431d5ae46a5816c70defce5 */
|
||||
* Stub hash: 5c7af89178bc4ea0f49fbf516d81f4fdaebece22 */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
@ -97,6 +97,16 @@ ZEND_END_ARG_INFO()
|
|||
|
||||
#define arginfo_zend_test_zend_ini_str arginfo_zend_get_current_func_name
|
||||
|
||||
#if defined(ZEND_CHECK_STACK_LIMIT)
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_zend_call_stack_get, 0, 0, IS_ARRAY, 1)
|
||||
ZEND_END_ARG_INFO()
|
||||
#endif
|
||||
|
||||
#if defined(ZEND_CHECK_STACK_LIMIT)
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_zend_call_stack_use_all, 0, 0, IS_LONG, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
#endif
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ZendTestNS2_namespaced_func, 0, 0, _IS_BOOL, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
|
@ -185,6 +195,12 @@ static ZEND_FUNCTION(zend_call_method);
|
|||
static ZEND_FUNCTION(zend_test_zend_ini_parse_quantity);
|
||||
static ZEND_FUNCTION(zend_test_zend_ini_parse_uquantity);
|
||||
static ZEND_FUNCTION(zend_test_zend_ini_str);
|
||||
#if defined(ZEND_CHECK_STACK_LIMIT)
|
||||
static ZEND_FUNCTION(zend_test_zend_call_stack_get);
|
||||
#endif
|
||||
#if defined(ZEND_CHECK_STACK_LIMIT)
|
||||
static ZEND_FUNCTION(zend_test_zend_call_stack_use_all);
|
||||
#endif
|
||||
static ZEND_FUNCTION(ZendTestNS2_namespaced_func);
|
||||
static ZEND_FUNCTION(ZendTestNS2_namespaced_deprecated_func);
|
||||
static ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_func);
|
||||
|
@ -235,6 +251,12 @@ static const zend_function_entry ext_functions[] = {
|
|||
ZEND_FE(zend_test_zend_ini_parse_quantity, arginfo_zend_test_zend_ini_parse_quantity)
|
||||
ZEND_FE(zend_test_zend_ini_parse_uquantity, arginfo_zend_test_zend_ini_parse_uquantity)
|
||||
ZEND_FE(zend_test_zend_ini_str, arginfo_zend_test_zend_ini_str)
|
||||
#if defined(ZEND_CHECK_STACK_LIMIT)
|
||||
ZEND_FE(zend_test_zend_call_stack_get, arginfo_zend_test_zend_call_stack_get)
|
||||
#endif
|
||||
#if defined(ZEND_CHECK_STACK_LIMIT)
|
||||
ZEND_FE(zend_test_zend_call_stack_use_all, arginfo_zend_test_zend_call_stack_use_all)
|
||||
#endif
|
||||
ZEND_NS_FALIAS("ZendTestNS2", namespaced_func, ZendTestNS2_namespaced_func, arginfo_ZendTestNS2_namespaced_func)
|
||||
ZEND_NS_DEP_FALIAS("ZendTestNS2", namespaced_deprecated_func, ZendTestNS2_namespaced_deprecated_func, arginfo_ZendTestNS2_namespaced_deprecated_func)
|
||||
ZEND_NS_FALIAS("ZendTestNS2", namespaced_aliased_func, zend_test_void_return, arginfo_ZendTestNS2_namespaced_aliased_func)
|
||||
|
|
|
@ -611,7 +611,7 @@ PHPDBG_API bool phpdbg_check_caught_ex(zend_execute_data *execute_data, zend_obj
|
|||
uint32_t op_num, i;
|
||||
zend_op_array *op_array = &execute_data->func->op_array;
|
||||
|
||||
if (execute_data->opline >= EG(exception_op) && execute_data->opline < EG(exception_op) + 3) {
|
||||
if (execute_data->opline >= EG(exception_op) && execute_data->opline < EG(exception_op) + 3 && EG(opline_before_exception)) {
|
||||
op = EG(opline_before_exception);
|
||||
} else {
|
||||
op = execute_data->opline;
|
||||
|
|
|
@ -228,8 +228,8 @@ STDOUT.WriteLine("Build dir: " + get_define('BUILD_DIR'));
|
|||
STDOUT.WriteLine("PHP Core: " + get_define('PHPDLL') + " and " + get_define('PHPLIB'));
|
||||
|
||||
ADD_SOURCES("Zend", "zend_language_parser.c zend_language_scanner.c \
|
||||
zend_ini_parser.c zend_ini_scanner.c zend_alloc.c zend_compile.c \
|
||||
zend_constants.c zend_exceptions.c \
|
||||
zend_ini_parser.c zend_ini_scanner.c zend_alloc.c zend_call_stack.c \
|
||||
zend_compile.c zend_constants.c zend_exceptions.c \
|
||||
zend_execute_API.c zend_highlight.c \
|
||||
zend_llist.c zend_vm_opcodes.c zend_opcode.c zend_operators.c zend_ptr_stack.c \
|
||||
zend_stack.c zend_variables.c zend.c zend_API.c zend_extensions.c \
|
||||
|
@ -303,6 +303,9 @@ if (VS_TOOLSET && VCVERS >= 1914) {
|
|||
|
||||
AC_DEFINE('HAVE_STRNLEN', 1);
|
||||
|
||||
AC_DEFINE('ZEND_STACK_GROWS_DOWNWARDS', 1)
|
||||
AC_DEFINE('ZEND_CHECK_STACK_LIMIT', 1)
|
||||
|
||||
ADD_SOURCES("main/streams", "streams.c cast.c memory.c filter.c plain_wrapper.c \
|
||||
userspace.c transports.c xp_socket.c mmap.c glob_wrapper.c");
|
||||
ADD_FLAG("CFLAGS_BD_MAIN_STREAMS", "/D ZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
/* Define the minimum supported version */
|
||||
#undef _WIN32_WINNT
|
||||
#undef NTDDI_VERSION
|
||||
#define _WIN32_WINNT 0x0601
|
||||
#define _WIN32_WINNT 0x0602
|
||||
#define NTDDI_VERSION 0x06010000
|
||||
|
||||
/* Default PHP / PEAR directories */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue