diff --git a/.github/workflows/test-suite.yml b/.github/workflows/test-suite.yml index 4c28ccca3561..e8f698e4e091 100644 --- a/.github/workflows/test-suite.yml +++ b/.github/workflows/test-suite.yml @@ -166,7 +166,7 @@ jobs: with: configurationParameters: >- ${{ matrix.asan && 'CFLAGS="-fsanitize=undefined,address -DZEND_TRACK_ARENA_ALLOC" LDFLAGS="-fsanitize=undefined,address"' || '' }} - ${{ matrix.variation && 'CFLAGS="-DZEND_RC_DEBUG=1 -DPROFITABILITY_CHECKS=0 -DZEND_VERIFY_FUNC_INFO=1 -DZEND_VERIFY_TYPE_INFERENCE"' || '' }} + ${{ matrix.variation && 'CFLAGS="-DZEND_RC_DEBUG=1 -DPROFITABILITY_CHECKS=0 -DZEND_VERIFY_FUNC_INFO=1 -DZEND_VERIFY_TYPE_INFERENCE" CXXFLAGS="-DZEND_VERIFY_TYPE_INFERENCE"' || '' }} ${{ (matrix.variation && fromJson(inputs.branch).jobs.LINUX_X64.config.variation_enable_zend_max_execution_timers) && '--enable-zend-max-execution-timers' || '' }} --${{ matrix.debug && 'enable' || 'disable' }}-debug ${{ matrix.debug && 'CXXFLAGS="-D_GLIBCXX_ASSERTIONS"' || '' }} diff --git a/NEWS b/NEWS index 705ff85b2a6e..11c9d1db1af8 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,9 @@ PHP NEWS . Sync Boost.Context assembly with 1.91.0. (kn1g78) . Fixed bug GH-22387 (AST pretty-printing drops meaningful parentheses around RHS of instanceof). (timwolla) + . Fixed bug GH-15672 and GH-15911 (Stack overflow when an internal function + recurses through zend_call_function, such as a self-attached SPL + iterator). (iliaal) - DBA: . Fixed OOB read on malformed length field in dba flatfile handler. (alhudz) diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 71e0c56a51c8..cb48e6234371 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -861,6 +861,14 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_ } } +#ifdef ZEND_CHECK_STACK_LIMIT + if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) { + zend_call_stack_size_error(); + zend_release_fcall_info_cache(fci_cache); + return SUCCESS; + } +#endif + call = zend_vm_stack_push_call_frame(call_info, func, fci->param_count, object_or_called_scope); uint32_t consumed_args = fci->param_count ? fci->consumed_args : 0; diff --git a/ext/opcache/tests/jit/gh22443.phpt b/ext/opcache/tests/jit/gh22443.phpt index 869329b79b5c..4baa3f99fc61 100644 --- a/ext/opcache/tests/jit/gh22443.phpt +++ b/ext/opcache/tests/jit/gh22443.phpt @@ -45,7 +45,7 @@ for ($k = 0; $k < 8; $k++) { $cold = [makeListener([$svc, 'coldMethod'])]; $s = 0; -for ($i = 0; $i < 4000000; $i++) { +for ($i = 0; $i < 400; $i++) { $s += invokeListeners($warm, 'e', [$i & 7, ($i >> 2) & 7]); } for ($j = 0; $j < 5; $j++) { diff --git a/ext/spl/tests/gh15672.phpt b/ext/spl/tests/gh15672.phpt new file mode 100644 index 000000000000..ff3feda46f7e --- /dev/null +++ b/ext/spl/tests/gh15672.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-15672 (MultipleIterator attached to itself overflows the C stack) +--SKIPIF-- + +--EXTENSIONS-- +zend_test +--INI-- +memory_limit=2G +zend.max_allowed_stack_size=512K +--FILE-- +attachIterator(new ArrayIterator([1, 2, 3]), "1"); +$m->attachIterator($m, 3); +foreach ($m as $key => $value) { +} +?> +--EXPECTREGEX-- +.*Maximum call stack size of \d+ bytes.*Infinite recursion\?.*thrown in .* on line \d+ diff --git a/ext/spl/tests/gh15911.phpt b/ext/spl/tests/gh15911.phpt new file mode 100644 index 000000000000..502b2baf616b --- /dev/null +++ b/ext/spl/tests/gh15911.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-15911 (AppendIterator appended to itself overflows the C stack) +--SKIPIF-- + +--EXTENSIONS-- +zend_test +--INI-- +memory_limit=2G +zend.max_allowed_stack_size=512K +--FILE-- +append($it); +foreach ($it as $v) { +} +?> +--EXPECTREGEX-- +.*Maximum call stack size of \d+ bytes.*Infinite recursion\?.*thrown in .* on line \d+