diff --git a/.cirrus.yml b/.cirrus.yml index f2db9f81aa50d..0aed3f6b23a10 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -25,4 +25,4 @@ task: tests_script: - export SKIP_IO_CAPTURE_TESTS=1 - export CI_NO_IPV6=1 - - sapi/cli/php run-tests.php -P -q -j2 -g FAIL,XFAIL,BORK,WARN,LEAK,XLEAK,SKIP --offline --show-diff --show-slow 1000 --set-timeout 120 -d zend_extension=opcache.so + - sapi/cli/php run-tests.php -P -q -j2 -g FAIL,BORK,LEAK,XLEAK --offline --show-diff --show-slow 1000 --set-timeout 120 -d zend_extension=opcache.so diff --git a/.editorconfig b/.editorconfig index 155d834fedfe8..7911bf8490b63 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,7 +9,7 @@ end_of_line = lf charset = utf-8 tab_width = 4 -[{*.{awk,bat,c,cpp,d,h,l,re,skl,w32,y},Makefile*}] +[{*.{awk,bat,c,cpp,d,dasc,h,l,re,skl,w32,y},Makefile*}] indent_size = 4 indent_style = tab diff --git a/.gdbinit b/.gdbinit index dfe56360ca5f2..6117922621068 100644 --- a/.gdbinit +++ b/.gdbinit @@ -318,7 +318,8 @@ define ____print_ht set $n = $n - 1 end - if $ht->u.v.flags & 4 + set $packed = $ht->u.v.flags & 4 + if $packed printf "Packed" else printf "Hash" @@ -329,36 +330,45 @@ define ____print_ht set $i = 0 set $ind = $ind + 1 while $i < $num - set $p = (Bucket*)($ht->arData + $i) + if $packed + set $val = (zval*)($ht->arPacked + $i) + set $key = (zend_string*)0 + set $h = $i + else + set $bucket = (Bucket*)($ht->arData + $i) + set $val = &$bucket->val + set $key = $bucket->key + set $h = $bucket->h + end set $n = $ind - if $p->val.u1.v.type > 0 + if $val->u1.v.type > 0 while $n > 0 printf " " set $n = $n - 1 end printf "[%d] ", $i - if $p->key - ____print_str $p->key->val $p->key->len + if $key + ____print_str $key->val $key->len printf " => " else - printf "%d => ", $p->h + printf "%d => ", $h end if $arg1 == 0 - printf "%p\n", (zval *)&$p->val + printf "%p\n", $val end if $arg1 == 1 - set $zval = (zval *)&$p->val + set $zval = $val ____printzv $zval 1 end if $arg1 == 2 - printf "%s\n", (char*)$p->val.value.ptr + printf "%s\n", (char*)$val->value.ptr end if $arg1 == 3 - set $func = (zend_function*)$p->val.value.ptr + set $func = (zend_function*)$val->value.ptr printf "\"%s\"\n", $func->common.function_name->val end if $arg1 == 4 - set $const = (zend_constant *)$p->val.value.ptr + set $const = (zend_constant *)$val->value.ptr ____printzv $const 1 end end diff --git a/.github/actions/test-linux/action.yml b/.github/actions/test-linux/action.yml index c7dab609820dd..a0ec94ed80c31 100644 --- a/.github/actions/test-linux/action.yml +++ b/.github/actions/test-linux/action.yml @@ -1,5 +1,8 @@ name: Test inputs: + testArtifacts: + default: null + required: false runTestsParameters: default: '' required: false @@ -18,10 +21,17 @@ runs: export PDO_DBLIB_TEST_USER="pdo_test" export PDO_DBLIB_TEST_PASS="password" export SKIP_IO_CAPTURE_TESTS=1 + export TEST_PHP_JUNIT=junit.out.xml sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \ -j$(/usr/bin/nproc) \ - -g FAIL,XFAIL,BORK,WARN,LEAK,XLEAK,SKIP \ + -g FAIL,BORK,LEAK,XLEAK \ --offline \ --show-diff \ --show-slow 1000 \ --set-timeout 120 + - uses: actions/upload-artifact@v3 + if: always() && inputs.testArtifacts != null + with: + name: ${{ github.job }}_${{ inputs.testArtifacts }} + path: ${{ github.workspace }}/junit.out.xml + retention-days: 5 diff --git a/.github/actions/test-macos/action.yml b/.github/actions/test-macos/action.yml index 99ac49b268c76..46c7d39444350 100644 --- a/.github/actions/test-macos/action.yml +++ b/.github/actions/test-macos/action.yml @@ -1,5 +1,8 @@ name: Test inputs: + testArtifacts: + default: null + required: false runTestsParameters: default: '' required: false @@ -11,10 +14,17 @@ runs: set -x export SKIP_IO_CAPTURE_TESTS=1 export CI_NO_IPV6=1 + export TEST_PHP_JUNIT=junit.out.xml sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \ -j$(sysctl -n hw.ncpu) \ - -g FAIL,XFAIL,BORK,WARN,LEAK,XLEAK,SKIP \ + -g FAIL,BORK,LEAK,XLEAK \ --offline \ --show-diff \ --show-slow 1000 \ --set-timeout 120 + - uses: actions/upload-artifact@v3 + if: always() && inputs.testArtifacts != null + with: + name: ${{ github.job }}_${{ inputs.testArtifacts }} + path: ${{ github.workspace }}/junit.out.xml + retention-days: 5 diff --git a/.github/actions/verify-generated-files/action.yml b/.github/actions/verify-generated-files/action.yml index a243a3b190af1..139dd84662411 100644 --- a/.github/actions/verify-generated-files/action.yml +++ b/.github/actions/verify-generated-files/action.yml @@ -6,9 +6,10 @@ runs: run: | set -x [[ "$OSTYPE" == "darwin"* ]] && export PATH="/usr/local/opt/bison/bin:$PATH" + scripts/dev/credits scripts/dev/genfiles Zend/zend_vm_gen.php + ext/tokenizer/tokenizer_data_gen.php build/gen_stub.php -f build/gen_stub.php --generate-optimizer-info - ext/tokenizer/tokenizer_data_gen.php - git add . -Nu && git diff --exit-code + git add . -N && git diff --exit-code diff --git a/.github/labeler.yml b/.github/labeler.yml index f5ce093a4774b..ddab485008955 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -146,6 +146,9 @@ "Extension: pspell": - ext/pspell/**/* +"Extension: random": +- ext/random/**/* + "Extension: readline": - ext/readline/**/* @@ -219,22 +222,22 @@ - ext/zlib/**/* "SAPI: apache2handler": -- ext/sapi/apache2handler/**/* +- sapi/apache2handler/**/* "SAPI: cgi": -- ext/sapi/cgi/**/* +- sapi/cgi/**/* "SAPI: cli": -- ext/sapi/cli/**/* +- sapi/cli/**/* "SAPI: fpm": -- ext/sapi/fpm/**/* +- sapi/fpm/**/* "SAPI: fuzzer": -- ext/sapi/fuzzer/**/* +- sapi/fuzzer/**/* "SAPI: litespeed": -- ext/sapi/litespeed/**/* +- sapi/litespeed/**/* "SAPI: phpdbg": -- ext/sapi/phpdbg/**/* \ No newline at end of file +- sapi/phpdbg/**/* diff --git a/.github/workflows/close-stale-feature-requests.yml b/.github/workflows/close-stale-feature-requests.yml new file mode 100644 index 0000000000000..362cbd6721801 --- /dev/null +++ b/.github/workflows/close-stale-feature-requests.yml @@ -0,0 +1,23 @@ +name: Close stale feature requests + +on: + schedule: + - cron: "0 0 * * *" + +jobs: + stale: + if: github.repository_owner == 'php' + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v4 + with: + days-before-close: 7 + days-before-stale: 90 + exempt-all-assignees: true + only-issue-labels: "Status: Requires RFC,Feature" + # Hack to skip PRs, unfortunately there's no option to disable PRs + only-pr-labels: inexistent-label + stale-issue-message: >- + There has not been any recent activity in this feature request. It will automatically be closed in 7 days + if no further action is taken. Please see https://github.com/probot/stale#is-closing-stale-issues-really-a-good-idea + to understand why we auto-close stale feature requests. diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 4d347323e89b3..73921ad6c073b 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -67,11 +67,13 @@ jobs: - name: Test uses: ./.github/actions/test-linux with: + testArtifacts: ${{ matrix.branch.name }}_${{ matrix.name }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }} runTestsParameters: >- ${{ matrix.run_tests_parameters }} - name: Test Tracing JIT uses: ./.github/actions/test-linux with: + testArtifacts: ${{ matrix.branch.name }}_${{ matrix.name }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }} Tracing JIT runTestsParameters: >- ${{ matrix.run_tests_parameters }} -d zend_extension=opcache.so @@ -80,6 +82,7 @@ jobs: - name: Test OpCache uses: ./.github/actions/test-linux with: + testArtifacts: ${{ matrix.branch.name }}_${{ matrix.name }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }} OpCache runTestsParameters: >- ${{ matrix.run_tests_parameters }} -d zend_extension=opcache.so @@ -87,6 +90,7 @@ jobs: - name: Test Function JIT uses: ./.github/actions/test-linux with: + testArtifacts: ${{ matrix.branch.name }}_${{ matrix.name }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }} Function JIT runTestsParameters: >- ${{ matrix.run_tests_parameters }} -d zend_extension=opcache.so @@ -127,9 +131,12 @@ jobs: run: sudo make install - name: Test uses: ./.github/actions/test-macos + with: + testArtifacts: ${{ matrix.branch.name }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }} - name: Test Tracing JIT uses: ./.github/actions/test-macos with: + testArtifacts: ${{ matrix.branch.name }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }} Tracing JIT runTestsParameters: >- -d zend_extension=opcache.so -d opcache.enable_cli=1 @@ -138,6 +145,7 @@ jobs: - name: Test OpCache uses: ./.github/actions/test-macos with: + testArtifacts: ${{ matrix.branch.name }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }} OpCache runTestsParameters: >- -d zend_extension=opcache.so -d opcache.enable_cli=1 @@ -145,6 +153,7 @@ jobs: - name: Test Function JIT uses: ./.github/actions/test-macos with: + testArtifacts: ${{ matrix.branch.name }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }} Function JIT runTestsParameters: >- -d zend_extension=opcache.so -d opcache.enable_cli=1 @@ -153,3 +162,34 @@ jobs: -d opcache.jit=1205 - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files + COVERAGE_DEBUG_NTS: + runs-on: ubuntu-20.04 + steps: + - name: git checkout + uses: actions/checkout@v2 + - name: Create mssql container + uses: ./.github/actions/mssql + - name: apt + uses: ./.github/actions/apt-x64 + - name: Install gcovr + run: sudo -H pip install gcovr + - name: ./configure + uses: ./.github/actions/configure-x64 + with: + configurationParameters: --enable-debug --disable-zts --enable-gcov + - name: make + run: make -j$(/usr/bin/nproc) >/dev/null + - name: make install + uses: ./.github/actions/install-linux + - name: Setup + uses: ./.github/actions/setup-x64 + # We only test with OpCache, the difference in coverage is negligible + - name: Test OpCache + uses: ./.github/actions/test-linux + with: + runTestsParameters: >- + -d zend_extension=opcache.so + -d opcache.enable_cli=1 + - name: Upload Test Coverage to Codecov.io + if: always() + run: bash <(curl -s https://codecov.io/bash) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 4a1619ab5d106..f5a943dc583d4 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -50,9 +50,12 @@ jobs: uses: ./.github/actions/setup-x64 - name: Test uses: ./.github/actions/test-linux + with: + testArtifacts: ${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }} - name: Test Tracing JIT uses: ./.github/actions/test-linux with: + testArtifacts: ${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }} Tracing JIT runTestsParameters: >- -d zend_extension=opcache.so -d opcache.enable_cli=1 @@ -78,9 +81,12 @@ jobs: run: sudo make install - name: Test uses: ./.github/actions/test-macos + with: + testArtifacts: ${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }} - name: Test Tracing JIT uses: ./.github/actions/test-macos with: + testArtifacts: ${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }} Tracing JIT runTestsParameters: >- -d zend_extension=opcache.so -d opcache.enable_cli=1 diff --git a/.gitignore b/.gitignore index 1d55b6d9e20da..afa85395322f5 100644 --- a/.gitignore +++ b/.gitignore @@ -281,6 +281,7 @@ tmp-php.ini # GitHub actions cache # ------------------------------------------------------------------------------ /branch-commit-cache.json +/junit.out.xml # ------------------------------------------------------------------------------ # Special cases to invert previous ignore patterns diff --git a/EXTENSIONS b/EXTENSIONS index 25cf9fbd6a981..1b745557bf5c8 100644 --- a/EXTENSIONS +++ b/EXTENSIONS @@ -375,6 +375,7 @@ STATUS: Working EXTENSION: mbstring PRIMARY MAINTAINER: Rui Hirokawa (2001 - 2013) Nikita Popov (2017 - 2020) + Alex Dowad (2021 - 2022) MAINTENANCE: Maintained STATUS: Working ------------------------------------------------------------------------------- @@ -425,6 +426,13 @@ MAINTENANCE: Unknown STATUS: Working SINCE: 4.0.2 ------------------------------------------------------------------------------- +EXTENSION: random +PRIMARY MAINTAINER Go Kudo (2022 - 2022) + Tim Düsterhus (2022 - 2022) +MAINTENANCE: Maintained +STATUS: Working +SINCE: 8.2.0 +------------------------------------------------------------------------------- EXTENSION: readline PRIMARY MAINTAINER: Unknown MAINTENANCE: Unknown diff --git a/NEWS b/NEWS index 38465be6766b1..7fb9b27dc7688 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,182 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.2.0alpha2 +?? ??? ????, PHP 8.2.0beta3 + +- Random: + . Fixed bug GH-9235 (non-existant $sequence parameter in stub for + PcgOneseq128XslRr64::__construct()). (timwolla) + . Removed redundant RuntimeExceptions from Randomizer methods. The + exceptions thrown by the engines will be exposed directly. (timwolla) + . Added extension specific Exceptions/Errors (RandomException, RandomError, + BrokenRandomEngineError). (timwolla) + +- Standard: + . Fixed bug #65489 (glob() basedir check is inconsistent). (Jakub Zelenka) + +04 Aug 2022, PHP 8.2.0beta2 + +- Core: + . Fixed bug GH-7900 (Arrow function with never return type compile-time + errors). (ilutov) + +- Date: + . Fixed bug GH-8730 (DateTime::diff miscalculation is same time zone of + different type). (Derick) + . Fixed bug GH-8964 (DateTime object comparison after applying delta less + than 1 second). (Derick) + . Fixed bug GH-9106: (DateInterval 1.5s added to DateTimeInterface is rounded + down since PHP 8.1.0). (Derick) + . Fixed bug #75035 (Datetime fails to unserialize "extreme" dates). + (Derick) + . Fixed bug #80483 (DateTime Object with 5-digit year can't unserialized). + (Derick) + . Fixed bug #81263 (Wrong result from DateTimeImmutable::diff). (Derick) + +- DBA: + . Fixed LMDB driver memory leak on DB creation failure (Girgias) + . Fixed GH-8856 (dba: lmdb: allow to override the MDB_NOSUBDIR flag). (Girgias) + +- FFI: + . Fixed bug GH-9090 (Support assigning function pointers in FFI). (Adam + Saponara) + +- Intl: + . Declared Transliterator::$id as readonly to unlock subclassing it. (Nicolas + Grekas) + +- OPcache: + . Fixed bug GH-9164 (Segfault in zend_accel_class_hash_copy). + (Arnaud, Sergei Turchanov) + +- PCNTL: + . Fixed pcntl_(get|set)priority error handling for MacOS. (Juan Morales) + +- Random: + . Fixed bug GH-9067 (random extension is not thread safe). (cmb) + . Fixed bug GH-9055 (segmentation fault if user engine throws). (timwolla) + . Fixed bug GH-9066 (signed integer overflow). (zeriyoshi) + . Fixed bug GH-9083 (undefined behavior during shifting). (timwolla) + . Fixed bug GH-9088, GH-9056 (incorrect expansion of bytes when + generating uniform integers within a given range). (timwolla) + . Fixed bug GH-9089 (Fix memory leak on Randomizer::__construct() + call twice). (zeriyoshi) + . Fixed bug GH-9212 (PcgOneseq128XslRr64::jump() should not allow negative + $advance). (Anton Smirnov) + . Changed Mt19937 to throw a ValueError instead of InvalidArgumentException + for invalid $mode. (timwolla) + . Splitted Random\Randomizer::getInt() (without arguments) to + Random\Randomizer::nextInt(). (zeriyoshi) + +- Sockets: + . Added SOL_FILTER socket option for Solaris. (David Carlier) + +- SPL: + . Fixed bug #69181 (READ_CSV|DROP_NEW_LINE drops newlines within fields). + (cmb) + . Fixed bug #65069 (GlobIterator incorrect handling of open_basedir check). + (Jakub Zelenka) + +21 Jul 2022, PHP 8.2.0beta1 + +- CLI: + . Updated the mime-type table for the builtin-server. (Ayesh Karunaratne) + . Fixed potential overflow for the builtin server via the + PHP_CLI_SERVER_WORKERS environment variable. (yiyuaner) + . Fixed GH-8575 by changing STDOUT, STDERR and STDIN to not close on resource + destruction. (Jakub Zelenka) + +- Core: + . Reduced the memory footprint of strings returned by var_export(), + json_encode(), serialize(), iconv_*(), mb_ereg*(), session_create_id(), + http_build_query(), strstr(), Reflection*::__toString(). (Arnaud) + . Fixed bug GH-8995 (WeakMap object reference offset causing TypeError). + (Tobias Bachert) + . Added error_log_mode ini setting. (Mikhail Galanin) + . Updated request startup messages. (Eric Norris) + +- COM: + . Fixed bug GH-8750 (Can not create VT_ERROR variant type). (cmb) + +- Filter: + . Added FILTER_FLAG_GLOBAL_RANGE to filter Global IPs. (vnsavage) + +- FPM: + . Added listen.setfib pool option to set route FIB on FreeBSD. (David Carlier) + . Added access.suppress_path pool option to filter access log entries. + (Mark Gallagher) + . Fixed on fpm scoreboard occasional warning on acquisition failure. + (Felix Wiedemann) + +- Opcache: + . Added initial support for JIT performance profiling generation + for macOs Instrument. (David Carlier) + . Fixed bug GH-8030 (Segfault with JIT and large match/switch statements). + (Arnaud) + . Added JIT support improvement for macOs for segments and executable permission + bit handling. (David Carlier) + . Added JIT buffer allocation near the .text section on FreeNSD. (David Carlier) + +- PCRE: + . Updated bundled libpcre to 10.40. (cmb) + +- PDO_Firebird: + . Fixed bug GH-8576 (Bad interpretation of length when char is UTF-8). (cmb) + +- Random: + . Added new random extension. (Go Kudo) + +- SPL: + . Widen iterator_to_array() and iterator_count()'s $iterator parameter to + iterable. (timwolla) + +- Standard: + . Implemented FR GH-8924 (str_split should return empty array for empty + string). (Michael Vorisek) + . Added ini_parse_quantity function to convert ini quantities shorthand + notation to int. (Dennis Snell) + . Enable arc4random_buf for Linux glibc 2.36 and onwards + for the random_bytes. (Cristian Rodriguez) + . Uses CCRandomGenerateBytes instead of arc4random_buf on macOs. (David Carlier). + +- Windows: + . Added preliminary support for (cross-)building for ARM64. (Yun Dou) + +07 Jul 2022, PHP 8.2.0alpha3 + +- Core: + . Uses safe_perealloc instead of perealloc for the + ZEND_PTR_STACK_RESIZE_IF_NEEDED to avoid possible overflows. (David Carlier) + +- DBA: + . Fixed LMDB driver hanging when attempting to delete a non-existing key + (Girgias) + +- Intl: + . Fixed build for ICU 69.x and onwards. (David Carlier) + +- Opcache: + . Allocate JIT buffer close to PHP .text segemnt to allow using direct + IP-relative calls and jumps. + (Su Tao, Wang Xue, Chen Hu, Lizhen Lizhen, Dmitry) + +- Sockets: + . Added TCP_CONGESTION socket option. (David Carlier) + . Added SO_ZEROCOPY/MSG_ZEROCOPY options. (David Carlier) + +- SPL: + . Uses safe_erealloc instead of erealloc to handle heap growth + for the SplHeap::insert method to avoid possible overflows. (David Carlier) + +- Standard: + . Fixed the crypt_sha256/512 api build with clang > 12. (David Carlier) + . Uses safe_erealloc instead of erealloc to handle options in getopt + to avoid possible overflows. (David Carlier) + +- Zip: + + . Implement fseek for zip stream when possible with libzip 1.9.1. (Remi) + +23 Jun 2022, PHP 8.2.0alpha2 - Core: . Fixed bug GH-8655 (Casting an object to array does not unwrap refcount=1 @@ -9,24 +185,26 @@ PHP NEWS warning). (ilutov) . Fixed bug GH-7821 and GH-8418 (Allow arbitrary const expressions in backed enums). (ilutov) + . Fixed bug GH-8810 (Incorrect lineno in backtrace of multi-line function + calls). (ilutov) + . Optimised code path for newly created file with the stream plain wrapper. (Max Kellermann) - Curl: . Added new constants from cURL 7.62 to 7.80. (Pierrick) . New function curl_upkeep(). (Pierrick) -- MBString: - . Backwards-compatible mappings for 0x5C/0x7E in Shift-JIS are restored, - after they had been changed in 8.1.0. (Alex Dowad) +- OpenSSL: + . Discard poll calls on socket when no timeout/non blocking/MSG_DONTWAIT. (Max Kellermann) -- ODBC: - . Fixed handling of single-key connection strings. (Calvin Buckley) - -- PDO_ODBC: - . Fixed handling of single-key connection strings. (Calvin Buckley) +- PCRE: + . Implemented FR #77726 (Allow null character in regex patterns). (cmb) - Standard: . Deprecated utf8_encode() and utf8_decode(). (Rowan Tommins) +- Streams: + . Discard poll calls on socket when no timeout/non blocking/MSG_DONTWAIT. (Max Kellermann) + 09 Jun 2022, PHP 8.2.0alpha1 - CLI: diff --git a/README.md b/README.md index d9b7bab54dffd..f98feb78823cb 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ web development. Fast, flexible and pragmatic, PHP powers everything from your blog to the most popular websites in the world. PHP is distributed under the [PHP License v3.01](LICENSE). -[![Build status](https://travis-ci.com/php/php-src.svg?branch=master)](https://travis-ci.com/php/php-src) +[![Push](https://github.com/php/php-src/actions/workflows/push.yml/badge.svg)](https://github.com/php/php-src/actions/workflows/push.yml) +[![Build status](https://travis-ci.com/php/php-src.svg?branch=master)](https://travis-ci.com/github/php/php-src) [![Build status](https://ci.appveyor.com/api/projects/status/meyur6fviaxgdwdy/branch/master?svg=true)](https://ci.appveyor.com/project/php/php-src) [![Build Status](https://dev.azure.com/phpazuredevops/php/_apis/build/status/php.php-src?branchName=master)](https://dev.azure.com/phpazuredevops/php/_build/latest?definitionId=1&branchName=master) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/php.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:php) diff --git a/UPGRADING b/UPGRADING index e28498efe9a80..39bc307be46f8 100644 --- a/UPGRADING +++ b/UPGRADING @@ -39,12 +39,18 @@ PHP 8.2 UPGRADE NOTES further details. - Standard: + . glob() returns empty array if all paths are restricted by open_basedir. + Previously the error was returned but that behavior was not consistent and + did not work correctly for all patterns. . strtolower() and strtoupper() are no longer locale-sensitive. They now perform ASCII case conversion, as if the locale were "C". Use mb_strtolower() if you want localized case conversion. Similarly, stristr, stripos, strripos, lcfirst, ucfirst, ucwords, str_ireplace, array_change_key_case and sorting with SORT_FLAG_CASE use ASCII case conversion. + . str_split() returns an empty array for an empty string now. Previously it + returned an array with a single empty string entry. mb_str_split() is not + affected by this change since it was already behaving like that. - SPL: . The following methods now enforce their signature: @@ -58,6 +64,9 @@ PHP 8.2 UPGRADE NOTES previously it was bool . SplFileObject::getChildren() now has a tentative return type of null, previously it was ?RecursiveIterator + . GlogIterator returns empty array if all paths are restricted by + open_basedir. Previously the error was returned but that behavior was not + consistent and did not work correctly. ======================================== 2. New Features @@ -71,6 +80,14 @@ PHP 8.2 UPGRADE NOTES RFC: https://wiki.php.net/rfc/null-false-standalone-types . Added support for readonly classes. RFC: https://wiki.php.net/rfc/readonly_classes + . Added support for true type. + RFC: https://wiki.php.net/rfc/true-type + . Added support for Disjoint Normal Form (DNF) types. + RFC: https://wiki.php.net/rfc/dnf_types + . Added error_log_mode ini setting that allows setting of permissions for + error log file. + . Added support for fetching properties of enums in constant expressions. + RFC: https://wiki.php.net/rfc/fetch_property_in_const_expressions - Curl: @@ -79,6 +96,11 @@ PHP 8.2 UPGRADE NOTES . Exposed multiple new constants from libcurl 7.62 to 7.80. . Added new function curl_upkeep() to perform any connection upkeep checks. +- DBA: + . The LMDB Driver now accepts the DBA_LMDB_USE_SUB_DIR or DBA_LMDB_NO_SUB_DIR + flags to determine if it should create a sub directory or not when creating + a database file. + - OCI8: . Added an oci8.prefetch_lob_size directive and oci_set_prefetch_lob() function to tune LOB query performance by reducing the number of @@ -99,6 +121,14 @@ PHP 8.2 UPGRADE NOTES possible to use numbered subpattern references, and the matches array will still contain numbered results. +- Random: + . New extension that organizes and consolidates existing implementations + related to random number generators. New, higher quality RNGs are available + and scope issues are eliminated. + RFC: https://wiki.php.net/rfc/rng_extension + RFC: https://wiki.php.net/rfc/random_extension_improvement + + ======================================== 3. Changes in SAPI modules ======================================== @@ -131,11 +161,10 @@ PHP 8.2 UPGRADE NOTES [new Foo, "Bar::method"] This does not affect normal method callables like "A::method" or - ["A", "method"]. A deprecation notice is only emitted on call. Both - is_callable() and the callable type will silently accept these callables - until support for them is removed entirely. + ["A", "method"]. RFC: https://wiki.php.net/rfc/deprecate_partially_supported_callables + RFC: https://wiki.php.net/rfc/partially-supported-callables-expand-deprecation-notices . The "${var}" and "${expr}" style string interpolations are deprecated and will be removed in PHP 9. Use "$var"/"{$var}" or "{${expr}}", respectively. @@ -161,9 +190,13 @@ PHP 8.2 UPGRADE NOTES 5. Changed Functions ======================================== +- Core + . str*cmp, str*pos, substr_compare functions, using binary safe string + comparison now return -1, 0 and 1. + - DBA . dba_open() and dba_popen() now have the following enforced function signature - dba_open(string $path, string $mode, ?string $handler = null, int $permission = 0o644, int $map_size = 0) + dba_open(string $path, string $mode, ?string $handler = null, int $permission = 0o644, int $map_size = 0, ?int $flags = null) . dba_fetch()'s optional skip argument is now at the end in line with PHP userland semantics its signature now is: dba_fetch(string|array $key, $dba, int $skip = 0): string|false @@ -171,6 +204,15 @@ PHP 8.2 UPGRADE NOTES dba_fetch(string|array $key, $skip, $dba): string|false is still accepted, but it is recommended to use the new standard variant. +- Random + . random_bytes() and random_int() now throw \Random\RandomException on CSPRNG failure. + Previously a plain \Exception was thrown. + +- SPL + . The $iterator parameter of iterator_to_array() and iterator_count() is + widened to iterable from Iterator, allowing arrays to be passed. + RFC: https://wiki.php.net/rfc/iterator_xyz_accept_array + ======================================== 6. New Functions ======================================== @@ -178,6 +220,9 @@ PHP 8.2 UPGRADE NOTES - Curl: . curl_upkeep() (libcurl >= 7.62.0) +- mysqli: + . mysqli_execute_query() + - Reflection: . ReflectionFunction::isAnonymous() . ReflectionMethod::hasPrototype() @@ -188,6 +233,15 @@ PHP 8.2 UPGRADE NOTES - Standard: . The peak memory usage can now be reset to the current usage thanks to memory_reset_peak_usage(). + . ini_parse_quantity(): Parses "shorthand bytes" quantities returned by + ini_get(). The function is suitable for parsing quantities whose int value + is in the range [PHP_INT_MIN, PHP_INT_MAX]. + Parsing and interpretation is consistent with ini_set() (see also the + "Changes to INI File Handling" section). + Caveats: Some ini settings may apply additional constraints to the resuling + int value, such as a smaller range, that will not be reflected by + ini_parse_quantity(). The `memory_limit` setting accepts values higher than + PHP_INT_MAX, than can not be parsed by ini_parse_quantity(). ======================================== 7. New Classes and Interfaces @@ -217,10 +271,14 @@ PHP 8.2 UPGRADE NOTES mysqli with libmysql and all relevant functionality has been removed. . The reconnect property of mysqli_driver has been removed. It was supported only by libmysql. . The INI directive mysqli.reconnect has been removed. + . The constant MYSQLI_IS_MARIADB has been deprecated. - OCI8: . The minimum Oracle Client library version required is now 11.2. +- PCRE: + . NUL characters (\0) in pattern strings are now supported. + - SQLite3: . sqlite3.defensive is now PHP_INI_USER. @@ -242,6 +300,7 @@ PHP 8.2 UPGRADE NOTES ======================================== - COM_DOTNET: + . DISP_E_PARAMNOTFOUND . LOCALE_NEUTRAL - Curl: @@ -323,6 +382,9 @@ PHP 8.2 UPGRADE NOTES . CURL_VERSION_UNICODE (libcurl >= 7.72.0) . CURL_VERSION_ZSTD (libcurl >= 7.72.0) +- Filter + . FILTER_FLAG_GLOBAL_RANGE + - Sockets: . SO_INCOMING_CPU . SO_MEMINFO @@ -337,11 +399,99 @@ PHP 8.2 UPGRADE NOTES . LOCAL_CREDS (NetBSD) . SO_BPF_EXTENSIONS . SO_SETFIB + . TCP_CONGESTION (Linux, FreeBSD) + . SO_ZEROCOPY (Linux) + . MSG_ZEROCOPY (Linux) ======================================== 11. Changes to INI File Handling ======================================== +- Parsing of some ill-formatted values will now trigger a warning when this was + silently ignored before. Interpretation of these values is not changed, for + backwards compatibility. This affects the following settings: + . bcmath.scale + . com.code_page + . default_socket_timeout + . fiber.stack_size + . hard_timeout + . intl.error_level + . ldap.max_links + . max_input_nesting_level + . max_input_vars + . mbstring.regex_retry_limit + . mbstring.regex_stack_limit + . mysqli.allow_local_infile + . mysqli.allow_persistent + . mysqli.default_port + . mysqli.max_links + . mysqli.max_persistent + . mysqli.reconnect + . mysqli.rollback_on_cached_plink + . mysqlnd.log_mask + . mysqlnd.mempool_default_size + . mysqlnd.net_read_buffer_size + . mysqlnd.net_read_timeout + . oci8.default_prefetch + . oci8.max_persistent + . oci8.persistent_timeout + . oci8.ping_interval + . oci8.prefetch_lob_size + . oci8.privileged_connect + . oci8.statement_cache_size + . odbc.allow_persistent + . odbc.check_persistent + . odbc.defaultbinmode + . odbc.default_cursortype + . odbc.defaultlrl + . odbc.max_links + . odbc.max_persistent + . opcache.consistency_checks + . opcache.file_update_protection + . opcache.force_restart_timeout + . opcache.interned_strings_buffer + . opcache.jit_bisect_limit + . opcache.jit_blacklist_root_trace + . opcache.jit_blacklist_side_trace + . opcache.jit_debug + . opcache.jit_hot_func + . opcache.jit_hot_loop + . opcache.jit_hot_return + . opcache.jit_hot_side_exit + . opcache.jit_max_exit_counters + . opcache.jit_max_loop_unrolls + . opcache.jit_max_polymorphic_calls + . opcache.jit_max_recursive_calls + . opcache.jit_max_recursive_returns + . opcache.jit_max_root_traces + . opcache.jit_max_side_traces + . opcache.log_verbosity_level + . opcache.max_file_size + . opcache.opt_debug_level + . opcache.optimization_level + . opcache.revalidate_freq + . output_buffering + . pcre.backtrack_limit + . pcre.recursion_limit + . pgsql.max_links + . pgsql.max_persistent + . post_max_size + . realpath_cache_size + . realpath_cache_ttl + . session.cache_expire + . session.cookie_lifetime + . session.gc_divisor + . session.gc_maxlifetime + . session.gc_probability + . soap.wsdl_cache_limit + . soap.wsdl_cache_ttl + . unserialize_max_depth + . upload_max_filesize + . user_ini.cache_ttl + . xmlrpc_error_number + . zend.assertions + . zlib.output_compression_level + ======================================== 12. Windows Support ======================================== @@ -349,6 +499,8 @@ PHP 8.2 UPGRADE NOTES - Core: . Windows specific error messages are no longer localized, but instead in English to better match PHP error messages. + . Preliminary and highly experimental support for building on ARM64 has been + added. - OCI8: . Since building against Oracle Client 10g is no longer supported anyway, @@ -356,12 +508,18 @@ PHP 8.2 UPGRADE NOTES --with-oci8-12c and --with-oci8-19 are still supported. - Zip: + . The Zip extension upgraded to version 1.21.0 . The Zip extension is now built as shared library (DLL) by default. ======================================== 13. Other Changes ======================================== +- CLI: + . The STDOUT, STDERR and STDIN are no longer closed on resource destruction + which is mostly when the CLI finishes. It is however still possible to + explicitly close those streams using fclose and similar. + - Core: . The iterable type is now a built-in compile time alias for array|Traversable. Error messages relating to iterable will therefore now use array|Traversable. diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 64cfbee3cf11b..47c42d48d4274 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -29,6 +29,29 @@ PHP 8.2 INTERNALS UPGRADE NOTES * A new ZEND_THREEWAY_COMPARE() macro has been introduced which does a three-way comparison of two integers and returns -1, 0 or 1 if the LHS is smaller, equal or larger than the RHS +* Deprecated zend_atoi() and zend_atol(). Use ZEND_STRTOL() for general purpose + string to long conversion, or a variant of zend_ini_parse_quantity() for + parsing ini quantities. +* The return types of the following object handlers has changed from int to zend_result + - zend_object_cast_t + - zend_object_count_elements_t + - zend_object_get_closure_t + - zend_object_do_operation_t +* Added a new zero_position argument to php_stream_fopen_from_fd_rel to reflect + if this a newly created file so the current file offset needs not to be checked. +* Added smart_str_trim_to_size(). The function trims the memory allocated for the + string. This can considerably reduce the memory footprint of strings smaller + than approximately 4096 bytes. +* smart_str_extract() and the spprintf family of functions now use + smart_str_trim_to_size() before returning the string. +* It is recommended to use smart_str_extract() or smart_str_trim_to_size() when + using the smart_str API. +* zend_is_callable_ex, and functions which call it such as zend_is_callable and + zend_fcall_info_init, will issue deprecation notices if passed values which + are deprecated (see main UPGRADING notes). To suppress the notice, e.g. to + avoid duplicates when processing the same value multiple times, pass or add + IS_CALLABLE_SUPPRESS_DEPRECATIONS to the check_flags parameter. +* Registered zend_observer_fcall_init handlers are now also called for internal functions. ======================== 2. Build system changes @@ -43,6 +66,11 @@ PHP 8.2 INTERNALS UPGRADE NOTES string_natural_case_compare_function(), and string_natural_compare_function() have been removed. They always returned SUCCESS and were a wrapper around strnatcmp_ex(). Use strnatcmp_ex() directly instead. + - The PHP API php_fgetcsv() now returns a HashTable* instead of having an in-out + zval parameter. + It now returns NULL on an empty line instead of [null]. + A new function php_bc_fgetcsv_empty_line() has been added to get a HashTable* which + represents [null]. b. ext/pdo - pdo_raise_impl_error()'s parameter sqlstate has been changed from const char * to pdo_error_type (aka char [6]). diff --git a/Zend/Optimizer/block_pass.c b/Zend/Optimizer/block_pass.c index e7f62a6814935..b176ba2704e26 100644 --- a/Zend/Optimizer/block_pass.c +++ b/Zend/Optimizer/block_pass.c @@ -300,7 +300,8 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array src->opcode != ZEND_FETCH_STATIC_PROP_R && src->opcode != ZEND_FETCH_DIM_R && src->opcode != ZEND_FETCH_OBJ_R && - src->opcode != ZEND_NEW) { + src->opcode != ZEND_NEW && + src->opcode != ZEND_FETCH_THIS) { src->result_type = IS_UNUSED; MAKE_NOP(opline); ++(*opt_count); diff --git a/Zend/Optimizer/dfa_pass.c b/Zend/Optimizer/dfa_pass.c index a103527613137..72e109b70f085 100644 --- a/Zend/Optimizer/dfa_pass.c +++ b/Zend/Optimizer/dfa_pass.c @@ -265,6 +265,32 @@ static bool safe_instanceof(zend_class_entry *ce1, zend_class_entry *ce2) { return instanceof_function(ce1, ce2); } +static inline bool can_elide_list_type( + const zend_script *script, const zend_op_array *op_array, + const zend_ssa_var_info *use_info, zend_type type) +{ + zend_type *single_type; + /* For intersection: result==false is failure, default is success. + * For union: result==true is success, default is failure. */ + bool is_intersection = ZEND_TYPE_IS_INTERSECTION(type); + ZEND_TYPE_FOREACH(type, single_type) { + if (ZEND_TYPE_HAS_LIST(*single_type)) { + ZEND_ASSERT(!is_intersection); + return can_elide_list_type(script, op_array, use_info, *single_type); + } + if (ZEND_TYPE_HAS_NAME(*single_type)) { + zend_string *lcname = zend_string_tolower(ZEND_TYPE_NAME(*single_type)); + zend_class_entry *ce = zend_optimizer_get_class_entry(script, op_array, lcname); + zend_string_release(lcname); + bool result = ce && safe_instanceof(use_info->ce, ce); + if (result == !is_intersection) { + return result; + } + } + } ZEND_TYPE_FOREACH_END(); + return is_intersection; +} + static inline bool can_elide_return_type_check( const zend_script *script, zend_op_array *op_array, zend_ssa *ssa, zend_ssa_op *ssa_op) { zend_arg_info *arg_info = &op_array->arg_info[-1]; @@ -286,22 +312,7 @@ static inline bool can_elide_return_type_check( } if (disallowed_types == MAY_BE_OBJECT && use_info->ce && ZEND_TYPE_IS_COMPLEX(arg_info->type)) { - zend_type *single_type; - /* For intersection: result==false is failure, default is success. - * For union: result==true is success, default is failure. */ - bool is_intersection = ZEND_TYPE_IS_INTERSECTION(arg_info->type); - ZEND_TYPE_FOREACH(arg_info->type, single_type) { - if (ZEND_TYPE_HAS_NAME(*single_type)) { - zend_string *lcname = zend_string_tolower(ZEND_TYPE_NAME(*single_type)); - zend_class_entry *ce = zend_optimizer_get_class_entry(script, op_array, lcname); - zend_string_release(lcname); - bool result = ce && safe_instanceof(use_info->ce, ce); - if (result == !is_intersection) { - return result; - } - } - } ZEND_TYPE_FOREACH_END(); - return is_intersection; + return can_elide_list_type(script, op_array, use_info, arg_info->type); } return false; @@ -680,13 +691,32 @@ static void zend_ssa_unlink_block(zend_op_array *op_array, zend_ssa *ssa, zend_b { if (block->predecessors_count == 1 && ssa->blocks[block_num].phis == NULL) { int *predecessors, i; + zend_basic_block *fe_fetch_block = NULL; ZEND_ASSERT(block->successors_count == 1); predecessors = &ssa->cfg.predecessors[block->predecessor_offset]; + if (block->predecessors_count == 1 && (block->flags & ZEND_BB_FOLLOW)) { + zend_basic_block *pred_block = &ssa->cfg.blocks[predecessors[0]]; + + if (pred_block->len > 0 && (pred_block->flags & ZEND_BB_REACHABLE)) { + if ((op_array->opcodes[pred_block->start + pred_block->len - 1].opcode == ZEND_FE_FETCH_R + || op_array->opcodes[pred_block->start + pred_block->len - 1].opcode == ZEND_FE_FETCH_RW) + && op_array->opcodes[pred_block->start + pred_block->len - 1].op2_type == IS_CV) { + fe_fetch_block = pred_block; + } + } + } for (i = 0; i < block->predecessors_count; i++) { zend_ssa_replace_control_link(op_array, ssa, predecessors[i], block_num, block->successors[0]); } zend_ssa_remove_block(op_array, ssa, block_num); + if (fe_fetch_block && fe_fetch_block->successors[0] == fe_fetch_block->successors[1]) { + /* The body of "foreach" loop was removed */ + int ssa_var = ssa->ops[fe_fetch_block->start + fe_fetch_block->len - 1].op2_def; + if (ssa_var >= 0) { + zend_ssa_remove_uses_of_var(ssa, ssa_var); + } + } } } diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c index 8317f9700ca6d..9373ad2adc63d 100644 --- a/Zend/Optimizer/sccp.c +++ b/Zend/Optimizer/sccp.c @@ -1721,7 +1721,7 @@ static zval *value_from_type_and_range(sccp_ctx *ctx, int var_num, zval *tmp) { } if (!(info->type & ((MAY_BE_ANY|MAY_BE_UNDEF)-MAY_BE_NULL))) { - if (ssa->vars[var_num].definition >= 0 + if (ssa->vars[var_num].definition >= 0 && ctx->scdf.op_array->opcodes[ssa->vars[var_num].definition].opcode == ZEND_VERIFY_RETURN_TYPE) { return NULL; } @@ -1729,10 +1729,18 @@ static zval *value_from_type_and_range(sccp_ctx *ctx, int var_num, zval *tmp) { return tmp; } if (!(info->type & ((MAY_BE_ANY|MAY_BE_UNDEF)-MAY_BE_FALSE))) { + if (ssa->vars[var_num].definition >= 0 + && ctx->scdf.op_array->opcodes[ssa->vars[var_num].definition].opcode == ZEND_VERIFY_RETURN_TYPE) { + return NULL; + } ZVAL_FALSE(tmp); return tmp; } if (!(info->type & ((MAY_BE_ANY|MAY_BE_UNDEF)-MAY_BE_TRUE))) { + if (ssa->vars[var_num].definition >= 0 + && ctx->scdf.op_array->opcodes[ssa->vars[var_num].definition].opcode == ZEND_VERIFY_RETURN_TYPE) { + return NULL; + } ZVAL_TRUE(tmp); return tmp; } diff --git a/Zend/Optimizer/zend_func_infos.h b/Zend/Optimizer/zend_func_infos.h index 6ace0a5081c6a..74f57797fdf06 100644 --- a/Zend/Optimizer/zend_func_infos.h +++ b/Zend/Optimizer/zend_func_infos.h @@ -7,9 +7,7 @@ static const func_info_t func_infos[] = { F1("get_class_methods", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), F1("get_included_files", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), FN("set_error_handler", MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_OBJECT|MAY_BE_NULL), - F0("restore_error_handler", MAY_BE_TRUE), FN("set_exception_handler", MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_OBJECT|MAY_BE_NULL), - F0("restore_exception_handler", MAY_BE_TRUE), F1("get_declared_classes", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), F1("get_declared_traits", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), F1("get_declared_interfaces", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), @@ -268,10 +266,8 @@ static const func_info_t func_infos[] = { #endif F1("mysqli_affected_rows", MAY_BE_LONG|MAY_BE_STRING), F1("mysqli_character_set_name", MAY_BE_STRING), - F0("mysqli_close", MAY_BE_TRUE), F1("mysqli_connect", MAY_BE_OBJECT|MAY_BE_FALSE), F1("mysqli_connect_error", MAY_BE_STRING|MAY_BE_NULL), - F0("mysqli_debug", MAY_BE_TRUE), F1("mysqli_error", MAY_BE_STRING), F1("mysqli_error_list", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_ARRAY), F1("mysqli_fetch_field", MAY_BE_OBJECT|MAY_BE_FALSE), @@ -300,7 +296,6 @@ static const func_info_t func_infos[] = { F1("mysqli_real_escape_string", MAY_BE_STRING), F1("mysqli_reap_async_query", MAY_BE_OBJECT|MAY_BE_BOOL), F1("mysqli_stmt_affected_rows", MAY_BE_LONG|MAY_BE_STRING), - F0("mysqli_stmt_close", MAY_BE_TRUE), F1("mysqli_stmt_error", MAY_BE_STRING), F1("mysqli_stmt_error_list", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_ARRAY), F1("mysqli_stmt_get_result", MAY_BE_OBJECT|MAY_BE_FALSE), @@ -311,7 +306,6 @@ static const func_info_t func_infos[] = { F1("mysqli_stmt_result_metadata", MAY_BE_OBJECT|MAY_BE_FALSE), F1("mysqli_stmt_sqlstate", MAY_BE_STRING), F1("mysqli_sqlstate", MAY_BE_STRING), - F0("mysqli_ssl_set", MAY_BE_TRUE), F1("mysqli_stat", MAY_BE_STRING|MAY_BE_FALSE), F1("mysqli_store_result", MAY_BE_OBJECT|MAY_BE_FALSE), F1("mysqli_use_result", MAY_BE_OBJECT|MAY_BE_FALSE), @@ -422,6 +416,7 @@ static const func_info_t func_infos[] = { F1("posix_getrlimit", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_FALSE), #endif F1("pspell_suggest", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_FALSE), + F1("random_bytes", MAY_BE_STRING), #if defined(HAVE_HISTORY_LIST) F1("readline_list_history", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), #endif @@ -438,7 +433,6 @@ static const func_info_t func_infos[] = { F1("socket_addrinfo_explain", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_ARRAY), FN("sodium_crypto_kx_client_session_keys", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), FN("sodium_crypto_kx_server_session_keys", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), - F0("sodium_crypto_generichash_update", MAY_BE_TRUE), #if defined(crypto_secretstream_xchacha20poly1305_ABYTES) FN("sodium_crypto_secretstream_xchacha20poly1305_init_push", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), #endif @@ -450,25 +444,13 @@ static const func_info_t func_infos[] = { F1("class_uses", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_STRING|MAY_BE_FALSE), F1("spl_classes", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_STRING), F1("spl_object_hash", MAY_BE_STRING), - F1("iterator_to_array", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF), F1("ob_get_flush", MAY_BE_STRING|MAY_BE_FALSE), F1("ob_get_clean", MAY_BE_STRING|MAY_BE_FALSE), F1("ob_list_handlers", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), F1("ob_get_status", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_ARRAY), - F0("krsort", MAY_BE_TRUE), - F0("ksort", MAY_BE_TRUE), - F0("asort", MAY_BE_TRUE), - F0("arsort", MAY_BE_TRUE), - F0("sort", MAY_BE_TRUE), - F0("usort", MAY_BE_TRUE), - F0("uasort", MAY_BE_TRUE), - F0("uksort", MAY_BE_TRUE), - F0("array_walk", MAY_BE_TRUE), - F0("array_walk_recursive", MAY_BE_TRUE), F1("compact", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF), FN("array_fill", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_ANY), F1("array_fill_keys", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF), - F0("shuffle", MAY_BE_TRUE), F1("array_replace", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF), F1("array_replace_recursive", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF), FN("array_keys", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING), @@ -544,12 +526,6 @@ static const func_info_t func_infos[] = { F1("md5_file", MAY_BE_STRING|MAY_BE_FALSE), F1("sha1", MAY_BE_STRING), F1("sha1_file", MAY_BE_STRING|MAY_BE_FALSE), -#if defined(HAVE_SYSLOG_H) - F0("closelog", MAY_BE_TRUE), -#endif -#if defined(HAVE_SYSLOG_H) - F0("syslog", MAY_BE_TRUE), -#endif #if defined(HAVE_INET_NTOP) F1("inet_ntop", MAY_BE_STRING|MAY_BE_FALSE), #endif @@ -595,7 +571,7 @@ static const func_info_t func_infos[] = { F1("str_rot13", MAY_BE_STRING), F1("str_shuffle", MAY_BE_STRING), F1("str_word_count", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_LONG), - F1("str_split", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), + FN("str_split", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), F1("strpbrk", MAY_BE_STRING|MAY_BE_FALSE), F1("utf8_encode", MAY_BE_STRING), F1("utf8_decode", MAY_BE_STRING), @@ -639,9 +615,7 @@ static const func_info_t func_infos[] = { F1("image_type_to_extension", MAY_BE_STRING|MAY_BE_FALSE), F1("getimagesize", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_FALSE), F1("getimagesizefromstring", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_FALSE), - F0("phpinfo", MAY_BE_TRUE), F1("phpversion", MAY_BE_STRING|MAY_BE_FALSE), - F0("phpcredits", MAY_BE_TRUE), F1("php_sapi_name", MAY_BE_STRING|MAY_BE_FALSE), F1("php_uname", MAY_BE_STRING), F1("php_ini_scanned_files", MAY_BE_STRING|MAY_BE_FALSE), @@ -677,7 +651,6 @@ static const func_info_t func_infos[] = { #endif F1("quoted_printable_decode", MAY_BE_STRING), F1("quoted_printable_encode", MAY_BE_STRING), - F1("random_bytes", MAY_BE_STRING), F1("soundex", MAY_BE_STRING), F1("stream_context_create", MAY_BE_RESOURCE), F1("stream_context_get_params", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY), diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 1b8abd71aee0e..5f7a06b2a19a3 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -1961,9 +1961,15 @@ static uint32_t assign_dim_array_result_type( value_type |= MAY_BE_NULL; } if (dim_op_type == IS_UNUSED) { + if (arr_type & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) { + tmp |= MAY_BE_ARRAY_PACKED; + } tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG; } else { if (dim_type & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) { + if (arr_type & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) { + tmp |= MAY_BE_ARRAY_PACKED; + } tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG; } if (dim_type & MAY_BE_STRING) { @@ -3253,24 +3259,34 @@ static zend_always_inline zend_result _zend_update_type_info( tmp |= t1 & (MAY_BE_RC1|MAY_BE_RCN); } if (opline->op2_type == IS_UNUSED) { - if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL)) { + if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) { key_type |= MAY_BE_ARRAY_PACKED; } if (t1 & MAY_BE_ARRAY) { - key_type |= (MAY_BE_HASH_ONLY(t1) || (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE))) ? + key_type |= MAY_BE_HASH_ONLY(t1) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG; } } else { if (t2 & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) { - key_type |= (MAY_BE_HASH_ONLY(t1) || (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE))) ? - MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG; + if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) { + key_type |= MAY_BE_ARRAY_PACKED; + } + if (t1 & MAY_BE_ARRAY) { + key_type |= MAY_BE_HASH_ONLY(t1) ? + MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG; + } } if (t2 & MAY_BE_STRING) { key_type |= MAY_BE_ARRAY_KEY_STRING; if (opline->op2_type != IS_CONST) { // FIXME: numeric string - key_type |= (MAY_BE_HASH_ONLY(t1) || (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE))) ? - MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG; + if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) { + key_type |= MAY_BE_ARRAY_PACKED; + } + if (t1 & MAY_BE_ARRAY) { + key_type |= MAY_BE_HASH_ONLY(t1) ? + MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG; + } } } if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) { @@ -3367,7 +3383,12 @@ static zend_always_inline zend_result _zend_update_type_info( ZEND_ASSERT(j < 0 && "There should only be one use"); } } - if (((tmp & MAY_BE_ARRAY) && (tmp & MAY_BE_ARRAY_KEY_ANY)) || opline->opcode == ZEND_FETCH_DIM_FUNC_ARG) { + if (((tmp & MAY_BE_ARRAY) && (tmp & MAY_BE_ARRAY_KEY_ANY)) + || opline->opcode == ZEND_FETCH_DIM_FUNC_ARG + || opline->opcode == ZEND_FETCH_DIM_R + || opline->opcode == ZEND_FETCH_DIM_IS + || opline->opcode == ZEND_FETCH_DIM_UNSET + || opline->opcode == ZEND_FETCH_LIST_R) { UPDATE_SSA_TYPE(tmp, ssa_op->op1_def); } else { /* invalid key type */ diff --git a/Zend/tests/bug48899-deprecated.phpt b/Zend/tests/bug48899-deprecated.phpt new file mode 100644 index 0000000000000..d731d57849c3e --- /dev/null +++ b/Zend/tests/bug48899-deprecated.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #48899 (is_callable returns true even if method does not exist in parent class) [original test with deprecated syntax] +--FILE-- +testIsCallable(); +$child->testIsCallable2(); + +?> +--EXPECTF-- +Deprecated: Callables of the form ["ChildClass", "parent::testIsCallable"] are deprecated in %s on line %d +bool(false) + +Deprecated: Callables of the form ["ChildClass", "static::testIsCallable2"] are deprecated in %s on line %d +bool(true) diff --git a/Zend/tests/bug48899.phpt b/Zend/tests/bug48899.phpt index 2cbf308c3eddc..6edf3076ab09f 100644 --- a/Zend/tests/bug48899.phpt +++ b/Zend/tests/bug48899.phpt @@ -7,10 +7,10 @@ class ParentClass { } class ChildClass extends ParentClass { public function testIsCallable() { - var_dump(is_callable(array($this, 'parent::testIsCallable'))); + var_dump(is_callable(array('ParentClass', 'testIsCallable'))); } public function testIsCallable2() { - var_dump(is_callable(array($this, 'static::testIsCallable2'))); + var_dump(is_callable(array('ChildClass', 'testIsCallable2'))); } } diff --git a/Zend/tests/bug69180-backtrace.phpt b/Zend/tests/bug69180-backtrace.phpt new file mode 100644 index 0000000000000..da463047a141d --- /dev/null +++ b/Zend/tests/bug69180-backtrace.phpt @@ -0,0 +1,119 @@ +--TEST-- +Bug #69180: Backtrace does not honor trait conflict resolution / method aliasing +--FILE-- + $v['class'] . '::' . $v['function'], debug_backtrace())); + + return '=' . $name; + } +} + +class Model { + use T { + T::__get as private __t_get; + } + + public function __get($name): string { + var_dump(__METHOD__); + return $this->__t_get($name); + } +} + +class X extends Model {} + +class Y extends Model { + public function __get($name): string { + var_dump(__METHOD__); + return parent::__get($name); + } +} + +class Z extends Model { + private function __x_get($name): string { + var_dump(__METHOD__); + return parent::__get($name); + } + + public function __get($name): string { + var_dump(__METHOD__); + return $this->__x_get($name); + } +} + +class P extends Model { + private function __t_get($name): string { + var_dump(__METHOD__); + return parent::__get($name); + } + + public function __get($name): string { + var_dump(__METHOD__); + return $this->__t_get($name); + } +} + +$m = new X(); +$m->a; + +echo "\n"; + +$m = new Y(); +$m->a; + +echo "\n"; + +$m = new Z(); +$m->a; + +echo "\n"; + +$m = new P(); +$m->a; + +?> +--EXPECT-- +string(12) "Model::__get" +string(8) "T::__get" +Array +( + [0] => Model::__t_get + [1] => Model::__get +) + +string(8) "Y::__get" +string(12) "Model::__get" +string(8) "T::__get" +Array +( + [0] => Model::__t_get + [1] => Model::__get + [2] => Y::__get +) + +string(8) "Z::__get" +string(10) "Z::__x_get" +string(12) "Model::__get" +string(8) "T::__get" +Array +( + [0] => Model::__t_get + [1] => Model::__get + [2] => Z::__x_get + [3] => Z::__get +) + +string(8) "P::__get" +string(10) "P::__t_get" +string(12) "Model::__get" +string(8) "T::__get" +Array +( + [0] => Model::__t_get + [1] => Model::__get + [2] => P::__t_get + [3] => P::__get +) diff --git a/Zend/tests/bug71622.phpt b/Zend/tests/bug71622.phpt index c23547788a034..59d4101df6837 100644 --- a/Zend/tests/bug71622.phpt +++ b/Zend/tests/bug71622.phpt @@ -17,7 +17,7 @@ class Abc { public static function run() { $method = "foobar"; getMethodName($method); - var_dump(is_callable("self::$method")); + var_dump(is_callable("Abc::$method")); self::$method(); } } diff --git a/Zend/tests/callable_self_parent_static_deprecation.phpt b/Zend/tests/callable_self_parent_static_deprecation.phpt index a6696d234bc50..d01713d429f7e 100644 --- a/Zend/tests/callable_self_parent_static_deprecation.phpt +++ b/Zend/tests/callable_self_parent_static_deprecation.phpt @@ -9,27 +9,52 @@ class A { class B extends A { public function test() { // Different callables using self/parent/static - echo "Test different callables\n"; - call_user_func("self::foo"); - call_user_func("parent::foo"); - call_user_func("static::foo"); - call_user_func(["self", "foo"]); - call_user_func(["parent", "foo"]); - call_user_func(["static", "foo"]); - call_user_func(["B", "self::foo"]); - call_user_func(["B", "parent::foo"]); - call_user_func(["B", "static::foo"]); - call_user_func(["B", "A::foo"]); + $variants = [ + '"self::foo"' => "self::foo", + '"parent::foo"' => "parent::foo", + '"static::foo"' => "static::foo", + '["self", "foo"]' => ["self", "foo"], + '["parent", "foo"]' => ["parent", "foo"], + '["static", "foo"]' => ["static", "foo"], + '["B", "self::foo"]' => ["B", "self::foo"], + '["B", "parent::foo"]' => ["B", "parent::foo"], + '["B", "static::foo"]' => ["B", "static::foo"], + '["B", "A::foo"]' => ["B", "A::foo"], + '[$this, "self::foo"]' => [$this, "self::foo"], + '[$this, "parent::foo"]' => [$this, "parent::foo"], + '[$this, "static::foo"]' => [$this, "static::foo"], + '[$this, "A::foo"]' => [$this, "A::foo"], + ]; + + echo "==> Test call_user_func\n"; + foreach ($variants as $description => $callable) { + echo "$description\n"; + call_user_func($callable); + } + echo "\n==> Test call_user_func_array\n"; + foreach ($variants as $description => $callable) { + echo "$description\n"; + call_user_func_array($callable, []); + } // Also applies to other things performing calls - echo "Test array_map()\n"; - array_map("self::foo", [1]); + echo "\n==> Test array_map\n"; + foreach ($variants as $description => $callable) { + echo "$description\n"; + array_map($callable, [1]); + } - echo "Test is_callable() -- should be silent\n"; - var_dump(is_callable("self::foo")); + echo "\n==> Test is_callable()\n"; + foreach ($variants as $description => $callable) { + echo "$description\n"; + var_dump(is_callable($callable)); + } - echo "Test callable type hint -- should be silent\n"; - $this->callableTypeHint("self::foo"); + echo "\n==> Test callable type hint\n"; + foreach ($variants as $description => $callable) { + echo "$description\n"; + $this->callableTypeHint($callable); + } } public function callableTypeHint(callable $c) {} @@ -40,30 +65,236 @@ $b->test(); ?> --EXPECTF-- -Test different callables +==> Test call_user_func +"self::foo" + +Deprecated: Use of "self" in callables is deprecated in %s on line %d +"parent::foo" + +Deprecated: Use of "parent" in callables is deprecated in %s on line %d +"static::foo" + +Deprecated: Use of "static" in callables is deprecated in %s on line %d +["self", "foo"] + +Deprecated: Use of "self" in callables is deprecated in %s on line %d +["parent", "foo"] + +Deprecated: Use of "parent" in callables is deprecated in %s on line %d +["static", "foo"] + +Deprecated: Use of "static" in callables is deprecated in %s on line %d +["B", "self::foo"] + +Deprecated: Callables of the form ["B", "self::foo"] are deprecated in %s on line %d +["B", "parent::foo"] + +Deprecated: Callables of the form ["B", "parent::foo"] are deprecated in %s on line %d +["B", "static::foo"] + +Deprecated: Callables of the form ["B", "static::foo"] are deprecated in %s on line %d +["B", "A::foo"] + +Deprecated: Callables of the form ["B", "A::foo"] are deprecated in %s on line %d +[$this, "self::foo"] + +Deprecated: Callables of the form ["B", "self::foo"] are deprecated in %s on line %d +[$this, "parent::foo"] + +Deprecated: Callables of the form ["B", "parent::foo"] are deprecated in %s on line %d +[$this, "static::foo"] + +Deprecated: Callables of the form ["B", "static::foo"] are deprecated in %s on line %d +[$this, "A::foo"] + +Deprecated: Callables of the form ["B", "A::foo"] are deprecated in %s on line %d + +==> Test call_user_func_array +"self::foo" + +Deprecated: Use of "self" in callables is deprecated in %s on line %d +"parent::foo" + +Deprecated: Use of "parent" in callables is deprecated in %s on line %d +"static::foo" + +Deprecated: Use of "static" in callables is deprecated in %s on line %d +["self", "foo"] + +Deprecated: Use of "self" in callables is deprecated in %s on line %d +["parent", "foo"] + +Deprecated: Use of "parent" in callables is deprecated in %s on line %d +["static", "foo"] + +Deprecated: Use of "static" in callables is deprecated in %s on line %d +["B", "self::foo"] + +Deprecated: Callables of the form ["B", "self::foo"] are deprecated in %s on line %d +["B", "parent::foo"] + +Deprecated: Callables of the form ["B", "parent::foo"] are deprecated in %s on line %d +["B", "static::foo"] + +Deprecated: Callables of the form ["B", "static::foo"] are deprecated in %s on line %d +["B", "A::foo"] + +Deprecated: Callables of the form ["B", "A::foo"] are deprecated in %s on line %d +[$this, "self::foo"] + +Deprecated: Callables of the form ["B", "self::foo"] are deprecated in %s on line %d +[$this, "parent::foo"] + +Deprecated: Callables of the form ["B", "parent::foo"] are deprecated in %s on line %d +[$this, "static::foo"] + +Deprecated: Callables of the form ["B", "static::foo"] are deprecated in %s on line %d +[$this, "A::foo"] + +Deprecated: Callables of the form ["B", "A::foo"] are deprecated in %s on line %d + +==> Test array_map +"self::foo" Deprecated: Use of "self" in callables is deprecated in %s on line %d +"parent::foo" Deprecated: Use of "parent" in callables is deprecated in %s on line %d +"static::foo" Deprecated: Use of "static" in callables is deprecated in %s on line %d +["self", "foo"] Deprecated: Use of "self" in callables is deprecated in %s on line %d +["parent", "foo"] Deprecated: Use of "parent" in callables is deprecated in %s on line %d +["static", "foo"] Deprecated: Use of "static" in callables is deprecated in %s on line %d +["B", "self::foo"] Deprecated: Callables of the form ["B", "self::foo"] are deprecated in %s on line %d +["B", "parent::foo"] Deprecated: Callables of the form ["B", "parent::foo"] are deprecated in %s on line %d +["B", "static::foo"] Deprecated: Callables of the form ["B", "static::foo"] are deprecated in %s on line %d +["B", "A::foo"] Deprecated: Callables of the form ["B", "A::foo"] are deprecated in %s on line %d -Test array_map() +[$this, "self::foo"] + +Deprecated: Callables of the form ["B", "self::foo"] are deprecated in %s on line %d +[$this, "parent::foo"] + +Deprecated: Callables of the form ["B", "parent::foo"] are deprecated in %s on line %d +[$this, "static::foo"] + +Deprecated: Callables of the form ["B", "static::foo"] are deprecated in %s on line %d +[$this, "A::foo"] + +Deprecated: Callables of the form ["B", "A::foo"] are deprecated in %s on line %d + +==> Test is_callable() +"self::foo" Deprecated: Use of "self" in callables is deprecated in %s on line %d -Test is_callable() -- should be silent bool(true) -Test callable type hint -- should be silent +"parent::foo" + +Deprecated: Use of "parent" in callables is deprecated in %s on line %d +bool(true) +"static::foo" + +Deprecated: Use of "static" in callables is deprecated in %s on line %d +bool(true) +["self", "foo"] + +Deprecated: Use of "self" in callables is deprecated in %s on line %d +bool(true) +["parent", "foo"] + +Deprecated: Use of "parent" in callables is deprecated in %s on line %d +bool(true) +["static", "foo"] + +Deprecated: Use of "static" in callables is deprecated in %s on line %d +bool(true) +["B", "self::foo"] + +Deprecated: Callables of the form ["B", "self::foo"] are deprecated in %s on line %d +bool(true) +["B", "parent::foo"] + +Deprecated: Callables of the form ["B", "parent::foo"] are deprecated in %s on line %d +bool(true) +["B", "static::foo"] + +Deprecated: Callables of the form ["B", "static::foo"] are deprecated in %s on line %d +bool(true) +["B", "A::foo"] + +Deprecated: Callables of the form ["B", "A::foo"] are deprecated in %s on line %d +bool(true) +[$this, "self::foo"] + +Deprecated: Callables of the form ["B", "self::foo"] are deprecated in %s on line %d +bool(true) +[$this, "parent::foo"] + +Deprecated: Callables of the form ["B", "parent::foo"] are deprecated in %s on line %d +bool(true) +[$this, "static::foo"] + +Deprecated: Callables of the form ["B", "static::foo"] are deprecated in %s on line %d +bool(true) +[$this, "A::foo"] + +Deprecated: Callables of the form ["B", "A::foo"] are deprecated in %s on line %d +bool(true) + +==> Test callable type hint +"self::foo" + +Deprecated: Use of "self" in callables is deprecated in %s on line %d +"parent::foo" + +Deprecated: Use of "parent" in callables is deprecated in %s on line %d +"static::foo" + +Deprecated: Use of "static" in callables is deprecated in %s on line %d +["self", "foo"] + +Deprecated: Use of "self" in callables is deprecated in %s on line %d +["parent", "foo"] + +Deprecated: Use of "parent" in callables is deprecated in %s on line %d +["static", "foo"] + +Deprecated: Use of "static" in callables is deprecated in %s on line %d +["B", "self::foo"] + +Deprecated: Callables of the form ["B", "self::foo"] are deprecated in %s on line %d +["B", "parent::foo"] + +Deprecated: Callables of the form ["B", "parent::foo"] are deprecated in %s on line %d +["B", "static::foo"] + +Deprecated: Callables of the form ["B", "static::foo"] are deprecated in %s on line %d +["B", "A::foo"] + +Deprecated: Callables of the form ["B", "A::foo"] are deprecated in %s on line %d +[$this, "self::foo"] + +Deprecated: Callables of the form ["B", "self::foo"] are deprecated in %s on line %d +[$this, "parent::foo"] + +Deprecated: Callables of the form ["B", "parent::foo"] are deprecated in %s on line %d +[$this, "static::foo"] + +Deprecated: Callables of the form ["B", "static::foo"] are deprecated in %s on line %d +[$this, "A::foo"] + +Deprecated: Callables of the form ["B", "A::foo"] are deprecated in %s on line %d diff --git a/Zend/tests/enum/empty-from.phpt b/Zend/tests/enum/empty-from.phpt new file mode 100644 index 0000000000000..db42c78ed31c7 --- /dev/null +++ b/Zend/tests/enum/empty-from.phpt @@ -0,0 +1,12 @@ +--TEST-- +Empty enum with from/tryFrom doens't segfault +--FILE-- + +--EXPECT-- +NULL diff --git a/Zend/tests/enum/magic-constants.phpt b/Zend/tests/enum/magic-constants.phpt new file mode 100644 index 0000000000000..7a11d7785d7a4 --- /dev/null +++ b/Zend/tests/enum/magic-constants.phpt @@ -0,0 +1,14 @@ +--TEST-- +Backed enums can contain magic constants +--FILE-- +value, "\n"; + +?> +--EXPECTF-- +%smagic-constants.php diff --git a/Zend/tests/fibers/call-to-ctor-of-terminated-fiber.phpt b/Zend/tests/fibers/call-to-ctor-of-terminated-fiber.phpt new file mode 100644 index 0000000000000..183932cafe630 --- /dev/null +++ b/Zend/tests/fibers/call-to-ctor-of-terminated-fiber.phpt @@ -0,0 +1,26 @@ +--TEST-- +Multiple calls to constructor are prevented after fiber terminated +--FILE-- +start()); +var_dump($fiber->getReturn()); + +$fiber->__construct(function () { + return 321; +}); + +?> +--EXPECTF-- +NULL +int(123) + +Fatal error: Uncaught FiberError: Cannot call constructor twice in %scall-to-ctor-of-terminated-fiber.php:%d +Stack trace: +#0 %scall-to-ctor-of-terminated-fiber.php(%d): Fiber->__construct(Object(Closure)) +#1 {main} + thrown in %scall-to-ctor-of-terminated-fiber.php on line %d diff --git a/Zend/tests/fibers/multiple-calls-to-ctor.phpt b/Zend/tests/fibers/multiple-calls-to-ctor.phpt new file mode 100644 index 0000000000000..28df144019fd4 --- /dev/null +++ b/Zend/tests/fibers/multiple-calls-to-ctor.phpt @@ -0,0 +1,20 @@ +--TEST-- +Multiple calls to constructor are prevented +--FILE-- +__construct(function () { + return 321; +}); + +?> +--EXPECTF-- +Fatal error: Uncaught FiberError: Cannot call constructor twice in %smultiple-calls-to-ctor.php:%d +Stack trace: +#0 %smultiple-calls-to-ctor.php(%d): Fiber->__construct(Object(Closure)) +#1 {main} + thrown in %smultiple-calls-to-ctor.php on line %d diff --git a/Zend/tests/fibers/signal-async.phpt b/Zend/tests/fibers/signal-async.phpt new file mode 100644 index 0000000000000..f1f5a2f4c8f2d --- /dev/null +++ b/Zend/tests/fibers/signal-async.phpt @@ -0,0 +1,37 @@ +--TEST-- +Prevent switching fibers when async signals are enabled +--EXTENSIONS-- +pcntl +posix +--FILE-- +start(); + +?> +--EXPECTF-- +Fiber start + +Fatal error: Uncaught FiberError: Cannot switch fibers in current execution context in %ssignal-async.php:%d +Stack trace: +#0 %ssignal-async.php(%d): Fiber::suspend() +#1 %ssignal-async.php(%d): {closure}(%d, Array) +#2 [internal function]: {closure}() +#3 %ssignal-async.php(%d): Fiber->start() +#4 {main} + thrown in %ssignal-async.php on line %d diff --git a/Zend/tests/fibers/signal-dispatch.phpt b/Zend/tests/fibers/signal-dispatch.phpt new file mode 100644 index 0000000000000..abde8e313d76e --- /dev/null +++ b/Zend/tests/fibers/signal-dispatch.phpt @@ -0,0 +1,46 @@ +--TEST-- +Prevent switching fibers when dispatching pending signals +--EXTENSIONS-- +pcntl +posix +--FILE-- +start(); + +echo $e, "\n"; + +$fiber->resume(); + +?> +--EXPECTF-- +Fiber start +FiberError: Cannot switch fibers in current execution context in %ssignal-dispatch.php:%d +Stack trace: +#0 %ssignal-dispatch.php(%d): Fiber::suspend() +#1 [internal function]: {closure}(%d, Array) +#2 %ssignal-dispatch.php(%d): pcntl_signal_dispatch() +#3 [internal function]: {closure}() +#4 %ssignal-dispatch.php(%d): Fiber->start() +#5 {main} +Fiber end diff --git a/Zend/tests/fibers/ticks.phpt b/Zend/tests/fibers/ticks.phpt new file mode 100644 index 0000000000000..fbd050c09b950 --- /dev/null +++ b/Zend/tests/fibers/ticks.phpt @@ -0,0 +1,33 @@ +--TEST-- +Prevent switching fibers in tick function +--FILE-- +start(); + +?> +--EXPECTF-- +1 + +Fatal error: Uncaught FiberError: Cannot switch fibers in current execution context in %sticks.php:%d +Stack trace: +#0 %sticks.php(%d): Fiber::suspend() +#1 %sticks.php(%d): {closure}() +#2 [internal function]: {closure}() +#3 %sticks.php(%d): Fiber->start() +#4 {main} + thrown in %sticks.php on line %d diff --git a/Zend/tests/gh7900.phpt b/Zend/tests/gh7900.phpt new file mode 100644 index 0000000000000..a4170fb1278fc --- /dev/null +++ b/Zend/tests/gh7900.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-7900: Arrow function with never return type compile-time errors +--INI-- +zend.assertions=1 +assert.exception=1 +--FILE-- + throw new \Exception('Here'); + +try { + var_dump($x()); +} catch (\Exception $e) { + echo $e->getMessage(), "\n"; +} + +try { + assert((fn(): never => 42) && false); +} catch (\Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Here +assert(fn(): never => 42 && false) diff --git a/Zend/tests/gh8810_1.phpt b/Zend/tests/gh8810_1.phpt new file mode 100644 index 0000000000000..ec48d4df0da4a --- /dev/null +++ b/Zend/tests/gh8810_1.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-8810: Fix reported line number of multi-line function call +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Exception in %s:4 +Stack trace: +#0 %s(7): foo('bar', 'baz') +#1 {main} + thrown in %s on line 4 diff --git a/Zend/tests/gh8810_2.phpt b/Zend/tests/gh8810_2.phpt new file mode 100644 index 0000000000000..df37057c7a7c3 --- /dev/null +++ b/Zend/tests/gh8810_2.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-8810: Fix reported line number of multi-line method call +--FILE-- + + b + (); + +?> +--EXPECTF-- +Fatal error: Uncaught Exception in %s:5 +Stack trace: +#0 %s(11): A->b() +#1 {main} + thrown in %s on line 5 diff --git a/Zend/tests/gh8810_3.phpt b/Zend/tests/gh8810_3.phpt new file mode 100644 index 0000000000000..99fb449ce2fc0 --- /dev/null +++ b/Zend/tests/gh8810_3.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-8810: Fix reported line number of multi-line closure call +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Exception in %s:4 +Stack trace: +#0 %s(6): {closure}('foo') +#1 {main} + thrown in %s on line 4 diff --git a/Zend/tests/gh8810_4.phpt b/Zend/tests/gh8810_4.phpt new file mode 100644 index 0000000000000..9abb317fbd10c --- /dev/null +++ b/Zend/tests/gh8810_4.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-8810: Fix reported line number of multi-line dynamic call +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Exception in %s:4 +Stack trace: +#0 %s(8): foo() +#1 {main} + thrown in %s on line 4 diff --git a/Zend/tests/gh8810_5.phpt b/Zend/tests/gh8810_5.phpt new file mode 100644 index 0000000000000..1b3a983181c9a --- /dev/null +++ b/Zend/tests/gh8810_5.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-8810: Fix reported line number of multi-line assert call +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught AssertionError: assert(false) in %s:3 +Stack trace: +#0 %s(3): assert(false, 'assert(false)') +#1 {main} + thrown in %s on line 3 diff --git a/Zend/tests/gh8810_6.phpt b/Zend/tests/gh8810_6.phpt new file mode 100644 index 0000000000000..452a859db5530 --- /dev/null +++ b/Zend/tests/gh8810_6.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-8810: Fix reported line number of multi-line static call +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Exception in %s:5 +Stack trace: +#0 %s(11): A::b() +#1 {main} + thrown in %s on line 5 diff --git a/Zend/tests/gh8810_7.phpt b/Zend/tests/gh8810_7.phpt new file mode 100644 index 0000000000000..b435b25d483a4 --- /dev/null +++ b/Zend/tests/gh8810_7.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-8810: Fix reported line number of multi-line new call +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Exception in %s:5 +Stack trace: +#0 %s(10): A->__construct() +#1 {main} + thrown in %s on line 5 diff --git a/Zend/tests/gh9136.phpt b/Zend/tests/gh9136.phpt new file mode 100644 index 0000000000000..22c4a056520d6 --- /dev/null +++ b/Zend/tests/gh9136.phpt @@ -0,0 +1,10 @@ +--TEST-- +GH-9136: Assertion when fetching property of magic constant in constant expression +--FILE-- +foo; + +?> +--EXPECTF-- +Warning: Attempt to read property "foo" on string in %s on line %d diff --git a/Zend/tests/gh9138.phpt b/Zend/tests/gh9138.phpt new file mode 100644 index 0000000000000..33550580527e0 --- /dev/null +++ b/Zend/tests/gh9138.phpt @@ -0,0 +1,11 @@ +--TEST-- +GH-9138: NULL pointer dereference when fetching property of "bad" list in constant expression +--FILE-- +e)] +class Foo {} + +?> +--EXPECTF-- +Fatal error: Cannot use empty array elements in arrays in %s on line %d diff --git a/Zend/tests/is_callable_trampoline_uaf-deprecated.phpt b/Zend/tests/is_callable_trampoline_uaf-deprecated.phpt new file mode 100644 index 0000000000000..fc853e471973c --- /dev/null +++ b/Zend/tests/is_callable_trampoline_uaf-deprecated.phpt @@ -0,0 +1,28 @@ +--TEST-- +is_callable() with trampoline should not caused UAF [original test with deprecated syntax] +--FILE-- +bar('foo')); + +?> +--EXPECTF-- +Deprecated: Use of "parent" in callables is deprecated in %s on line %d +bool(false) diff --git a/Zend/tests/is_callable_trampoline_uaf.phpt b/Zend/tests/is_callable_trampoline_uaf.phpt index 2410864410ab4..a36a995b8d673 100644 --- a/Zend/tests/is_callable_trampoline_uaf.phpt +++ b/Zend/tests/is_callable_trampoline_uaf.phpt @@ -6,7 +6,7 @@ is_callable() with trampoline should not caused UAF class B {} class A extends B { public function bar($func) { - var_dump(is_callable(array('parent', 'foo'))); + var_dump(is_callable(array('B', 'foo'))); } public function __call($func, $args) { diff --git a/Zend/tests/iterable_or_null.phpt b/Zend/tests/iterable_or_null.phpt index 3585e449caee2..a44e858bce92e 100644 --- a/Zend/tests/iterable_or_null.phpt +++ b/Zend/tests/iterable_or_null.phpt @@ -40,8 +40,8 @@ try { ?> --EXPECT-- -zend_iterable(): Argument #1 ($arg1) must be of type iterable, string given -zend_iterable(): Argument #1 ($arg1) must be of type iterable, int given -zend_iterable(): Argument #1 ($arg1) must be of type iterable, null given -zend_iterable(): Argument #2 ($arg2) must be of type ?iterable, string given +zend_iterable(): Argument #1 ($arg1) must be of type Traversable|array, string given +zend_iterable(): Argument #1 ($arg1) must be of type Traversable|array, int given +zend_iterable(): Argument #1 ($arg1) must be of type Traversable|array, null given +zend_iterable(): Argument #2 ($arg2) must be of type Traversable|array|null, string given diff --git a/Zend/tests/lsb_013.phpt b/Zend/tests/lsb_013.phpt index 3af7f1bea7eb0..c973db9059633 100644 --- a/Zend/tests/lsb_013.phpt +++ b/Zend/tests/lsb_013.phpt @@ -17,8 +17,15 @@ class Test2 extends Test1 { Test1::test(); Test2::test(); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Use of "static" in callables is deprecated in %s on line %d bool(false) + +Deprecated: Use of "static" in callables is deprecated in %s on line %d bool(false) + +Deprecated: Use of "static" in callables is deprecated in %s on line %d bool(true) + +Deprecated: Use of "static" in callables is deprecated in %s on line %d bool(true) diff --git a/Zend/tests/prop_const_expr/attributes.phpt b/Zend/tests/prop_const_expr/attributes.phpt new file mode 100644 index 0000000000000..96ebb9191443f --- /dev/null +++ b/Zend/tests/prop_const_expr/attributes.phpt @@ -0,0 +1,44 @@ +--TEST-- +Allow fetching properties in attributes +--EXTENSIONS-- +reflection +--FILE-- +name)] +#[Attr(A::B->value)] +#[Attr(A::B?->name)] +#[Attr(A::B?->value)] +class C {} + +foreach ((new ReflectionClass(C::class))->getAttributes() as $reflectionAttribute) { + var_dump($reflectionAttribute->newInstance()); +} + +?> +--EXPECT-- +object(Attr)#1 (1) { + ["value"]=> + string(1) "B" +} +object(Attr)#1 (1) { + ["value"]=> + string(1) "C" +} +object(Attr)#1 (1) { + ["value"]=> + string(1) "B" +} +object(Attr)#1 (1) { + ["value"]=> + string(1) "C" +} diff --git a/Zend/tests/prop_const_expr/basic.phpt b/Zend/tests/prop_const_expr/basic.phpt new file mode 100644 index 0000000000000..7499e7c55e9ee --- /dev/null +++ b/Zend/tests/prop_const_expr/basic.phpt @@ -0,0 +1,27 @@ +--TEST-- +Allow fetching properties in constant expressions on enums +--FILE-- +name; +const A_value = A::Case->value; + +var_dump(A_name); +var_dump(A_value); + +const A_name_nullsafe = A::Case?->name; +const A_value_nullsafe = A::Case?->value; + +var_dump(A_name_nullsafe); +var_dump(A_value_nullsafe); + +?> +--EXPECT-- +string(4) "Case" +string(7) "A::Case" +string(4) "Case" +string(7) "A::Case" diff --git a/Zend/tests/prop_const_expr/basic_nullsafe.phpt b/Zend/tests/prop_const_expr/basic_nullsafe.phpt new file mode 100644 index 0000000000000..da870c0328b0a --- /dev/null +++ b/Zend/tests/prop_const_expr/basic_nullsafe.phpt @@ -0,0 +1,46 @@ +--TEST-- +Nullsafe property constant expression +--FILE-- +test; +var_dump(A); + +const B = (null)?->test->test; +var_dump(B); + +const C = (null)->test?->test; +var_dump(C); + +const D = (null)?->test['test']; +var_dump(D); + +const E = (null)['test']?->test; +var_dump(E); + +const F = (null)?->{new Printer}; +var_dump(F); + +const G = (null)?->test + (new Printer ? 1 : 0); +var_dump(G); + +?> +--EXPECTF-- +NULL +NULL + +Warning: Attempt to read property "test" on null in %s on line %d +NULL +NULL + +Warning: Trying to access array offset on value of type null in %s on line %d +NULL +NULL +Printer +int(1) diff --git a/Zend/tests/prop_const_expr/class_const.phpt b/Zend/tests/prop_const_expr/class_const.phpt new file mode 100644 index 0000000000000..ff49ef58be2d4 --- /dev/null +++ b/Zend/tests/prop_const_expr/class_const.phpt @@ -0,0 +1,27 @@ +--TEST-- +Allow fetching properties in class constants +--FILE-- +name; + const A_value = A::Case->value; + const A_name_nullsafe = A::Case?->name; + const A_value_nullsafe = A::Case?->value; +} + +var_dump(C::A_name); +var_dump(C::A_value); +var_dump(C::A_name_nullsafe); +var_dump(C::A_value_nullsafe); + +?> +--EXPECT-- +string(4) "Case" +string(7) "A::Case" +string(4) "Case" +string(7) "A::Case" diff --git a/Zend/tests/prop_const_expr/default_args.phpt b/Zend/tests/prop_const_expr/default_args.phpt new file mode 100644 index 0000000000000..9046ddc82942c --- /dev/null +++ b/Zend/tests/prop_const_expr/default_args.phpt @@ -0,0 +1,34 @@ +--TEST-- +Property fetch in default argument +--FILE-- +name, + $value = A::B->value, + $nameNullsafe = A::B?->name, + $valueNullsafe = A::B?->value, +) { + var_dump($name); + var_dump($value); + var_dump($nameNullsafe); + var_dump($valueNullsafe); +} + +test(); +test('D', 'E', 'F', 'G'); + +?> +--EXPECT-- +string(1) "B" +string(1) "C" +string(1) "B" +string(1) "C" +string(1) "D" +string(1) "E" +string(1) "F" +string(1) "G" diff --git a/Zend/tests/prop_const_expr/enum_initializer.phpt b/Zend/tests/prop_const_expr/enum_initializer.phpt new file mode 100644 index 0000000000000..9b5c0314b69b1 --- /dev/null +++ b/Zend/tests/prop_const_expr/enum_initializer.phpt @@ -0,0 +1,30 @@ +--TEST-- +Property fetch in enum initializers +--FILE-- +name; + case F = A::B->value; +} + +enum G: string { + case H = A::B?->name; + case I = A::B?->value; +} + +var_dump(D::E->value); +var_dump(D::F->value); +var_dump(G::H->value); +var_dump(G::I->value); + +?> +--EXPECT-- +string(1) "B" +string(1) "C" +string(1) "B" +string(1) "C" diff --git a/Zend/tests/prop_const_expr/lhs_class_not_found.phpt b/Zend/tests/prop_const_expr/lhs_class_not_found.phpt new file mode 100644 index 0000000000000..9d10ec0f7b87c --- /dev/null +++ b/Zend/tests/prop_const_expr/lhs_class_not_found.phpt @@ -0,0 +1,13 @@ +--TEST-- +Property constant expression lhs error +--FILE-- +prop; + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Class "A" not found in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/prop_const_expr/lhs_class_not_found_nullsafe.phpt b/Zend/tests/prop_const_expr/lhs_class_not_found_nullsafe.phpt new file mode 100644 index 0000000000000..76bf62b2eda15 --- /dev/null +++ b/Zend/tests/prop_const_expr/lhs_class_not_found_nullsafe.phpt @@ -0,0 +1,13 @@ +--TEST-- +Nullsafe property constant expression lhs error +--FILE-- +prop; + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Class "A" not found in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/prop_const_expr/lhs_non_object.phpt b/Zend/tests/prop_const_expr/lhs_non_object.phpt new file mode 100644 index 0000000000000..357c58c3c0e30 --- /dev/null +++ b/Zend/tests/prop_const_expr/lhs_non_object.phpt @@ -0,0 +1,18 @@ +--TEST-- +Property constant expression lhs wrong type +--FILE-- +prop; +var_dump(A_prop); + +const A_prop_nullsafe = (42)?->prop; +var_dump(A_prop_nullsafe); + +?> +--EXPECTF-- +Warning: Attempt to read property "prop" on int in %s on line %d +NULL + +Warning: Attempt to read property "prop" on int in %s on line %d +NULL diff --git a/Zend/tests/prop_const_expr/non_enums.phpt b/Zend/tests/prop_const_expr/non_enums.phpt new file mode 100644 index 0000000000000..e045d4378fa06 --- /dev/null +++ b/Zend/tests/prop_const_expr/non_enums.phpt @@ -0,0 +1,17 @@ +--TEST-- +Disallow fetching properties in constant expressions on non-enums +--FILE-- +prop; + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Fetching properties on non-enums in constant expressions is not allowed in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/prop_const_expr/non_enums_catchable.phpt b/Zend/tests/prop_const_expr/non_enums_catchable.phpt new file mode 100644 index 0000000000000..6f410ac7acbe7 --- /dev/null +++ b/Zend/tests/prop_const_expr/non_enums_catchable.phpt @@ -0,0 +1,26 @@ +--TEST-- +RHS gets evaluated before throwing error when accessing properties on non-enums in constant expressions +--FILE-- +{new Printer ? 'printer' : null}; + +?> +--EXPECTF-- +Printer + +Fatal error: Uncaught Error: Fetching properties on non-enums in constant expressions is not allowed in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/prop_const_expr/non_enums_cost.phpt b/Zend/tests/prop_const_expr/non_enums_cost.phpt new file mode 100644 index 0000000000000..29311aa9ecaeb --- /dev/null +++ b/Zend/tests/prop_const_expr/non_enums_cost.phpt @@ -0,0 +1,18 @@ +--TEST-- +Disallow fetching properties in constant expressions on non-enums even if lhs is other const +--FILE-- +prop; + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Fetching properties on non-enums in constant expressions is not allowed in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/prop_const_expr/non_enums_nullsafe.phpt b/Zend/tests/prop_const_expr/non_enums_nullsafe.phpt new file mode 100644 index 0000000000000..428651c195e66 --- /dev/null +++ b/Zend/tests/prop_const_expr/non_enums_nullsafe.phpt @@ -0,0 +1,17 @@ +--TEST-- +Disallow nullsafe fetching properties in constant expressions on non-enums +--FILE-- +prop; + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Fetching properties on non-enums in constant expressions is not allowed in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/prop_const_expr/non_enums_rhs.phpt b/Zend/tests/prop_const_expr/non_enums_rhs.phpt new file mode 100644 index 0000000000000..0bffe9d8e02f5 --- /dev/null +++ b/Zend/tests/prop_const_expr/non_enums_rhs.phpt @@ -0,0 +1,26 @@ +--TEST-- +Error when fetching properties on non-enums in constant expressions is catchable +--FILE-- +prop) {} + +function test() { + try { + foo(); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } +} + +test(); +test(); + +?> +--EXPECT-- +Fetching properties on non-enums in constant expressions is not allowed +Fetching properties on non-enums in constant expressions is not allowed diff --git a/Zend/tests/prop_const_expr/property_initializer.phpt b/Zend/tests/prop_const_expr/property_initializer.phpt new file mode 100644 index 0000000000000..3cfe5a87ffc65 --- /dev/null +++ b/Zend/tests/prop_const_expr/property_initializer.phpt @@ -0,0 +1,28 @@ +--TEST-- +Property fetch in property initializer +--FILE-- +name; + public int $e = A::B->value; + public string $f = A::B?->name; + public int $g = A::B?->value; +} + +$c = new C(); +var_dump($c->d); +var_dump($c->e); +var_dump($c->f); +var_dump($c->g); + +?> +--EXPECT-- +string(1) "B" +int(42) +string(1) "B" +int(42) diff --git a/Zend/tests/prop_const_expr/rhs_object.phpt b/Zend/tests/prop_const_expr/rhs_object.phpt new file mode 100644 index 0000000000000..d9d01b81cbe3c --- /dev/null +++ b/Zend/tests/prop_const_expr/rhs_object.phpt @@ -0,0 +1,18 @@ +--TEST-- +Property constant expression rhs wrong type +--FILE-- +{new B}; + +var_dump(A_prop); + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Object of class B could not be converted to string in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/prop_const_expr/rhs_object_nullsafe.phpt b/Zend/tests/prop_const_expr/rhs_object_nullsafe.phpt new file mode 100644 index 0000000000000..72242b16a42e5 --- /dev/null +++ b/Zend/tests/prop_const_expr/rhs_object_nullsafe.phpt @@ -0,0 +1,18 @@ +--TEST-- +Nullsafe property constant expression rhs wrong type +--FILE-- +{new B}; + +var_dump(A_prop); + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Object of class B could not be converted to string in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/prop_const_expr/rhs_prop_not_found.phpt b/Zend/tests/prop_const_expr/rhs_prop_not_found.phpt new file mode 100644 index 0000000000000..0994075902b27 --- /dev/null +++ b/Zend/tests/prop_const_expr/rhs_prop_not_found.phpt @@ -0,0 +1,22 @@ +--TEST-- +Property not found error +--FILE-- +prop; +var_dump(A_prop); + +const A_prop_nullsafe = A::B?->prop; +var_dump(A_prop_nullsafe); + +?> +--EXPECTF-- +Warning: Undefined property: A::$prop in %s on line %d +NULL + +Warning: Undefined property: A::$prop in %s on line %d +NULL diff --git a/Zend/tests/prop_const_expr/static_initalizer.phpt b/Zend/tests/prop_const_expr/static_initalizer.phpt new file mode 100644 index 0000000000000..837ddcd513da8 --- /dev/null +++ b/Zend/tests/prop_const_expr/static_initalizer.phpt @@ -0,0 +1,29 @@ +--TEST-- +Allow fetching properties in static initializer +--FILE-- +name; + static $value = A::Case->value; + static $nameNullsafe = A::Case?->name; + static $valueNullsafe = A::Case?->value; + + var_dump($name); + var_dump($value); + var_dump($nameNullsafe); + var_dump($valueNullsafe); +} + +foo(); + +?> +--EXPECT-- +string(4) "Case" +string(7) "A::Case" +string(4) "Case" +string(7) "A::Case" diff --git a/Zend/tests/prop_const_expr/static_property_initializer.phpt b/Zend/tests/prop_const_expr/static_property_initializer.phpt new file mode 100644 index 0000000000000..825c8d0907f3e --- /dev/null +++ b/Zend/tests/prop_const_expr/static_property_initializer.phpt @@ -0,0 +1,27 @@ +--TEST-- +Property fetch in static property initializer +--FILE-- +name; + public static int $e = A::B->value; + public static string $f = A::B?->name; + public static int $g = A::B?->value; +} + +var_dump(C::$d); +var_dump(C::$e); +var_dump(C::$f); +var_dump(C::$g); + +?> +--EXPECT-- +string(1) "B" +int(42) +string(1) "B" +int(42) diff --git a/Zend/tests/readonly_props/array_append_initialization.phpt b/Zend/tests/readonly_props/array_append_initialization.phpt index 079fecb8b3373..d9b3e8c074438 100644 --- a/Zend/tests/readonly_props/array_append_initialization.phpt +++ b/Zend/tests/readonly_props/array_append_initialization.phpt @@ -19,7 +19,11 @@ function init() { var_dump($c->a); } -(new C)->init(); +try { + (new C)->init(); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} try { init(); @@ -29,8 +33,5 @@ try { ?> --EXPECT-- -array(1) { - [0]=> - int(1) -} -Cannot initialize readonly property C::$a from global scope +Cannot indirectly modify readonly property C::$a +Cannot indirectly modify readonly property C::$a diff --git a/Zend/tests/readonly_props/gh7942.phpt b/Zend/tests/readonly_props/gh7942.phpt new file mode 100644 index 0000000000000..89db53439a2f2 --- /dev/null +++ b/Zend/tests/readonly_props/gh7942.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-7942: Disallow assigning reference to unset readonly property +--FILE-- +bar = &$bar; + } +} + +try { + $i = 42; + new Foo($i); +} catch (Error $e) { + echo $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Cannot indirectly modify readonly property Foo::$bar diff --git a/Zend/tests/readonly_props/variation.phpt b/Zend/tests/readonly_props/variation.phpt new file mode 100644 index 0000000000000..a8ea4be60887e --- /dev/null +++ b/Zend/tests/readonly_props/variation.phpt @@ -0,0 +1,118 @@ +--TEST-- +Readonly variations +--FILE-- +prop = 1; + } + + public function r() { + echo $this->prop; + } + + public function w() { + $this->prop = 1; + echo 'done'; + } + + public function rw() { + $this->prop += 1; + echo 'done'; + } + + public function im() { + $this->prop[] = 1; + echo 'done'; + } + + public function is() { + echo (int) isset($this->prop); + } + + public function us() { + unset($this->prop); + echo 'done'; + } +} + +function r($test) { + echo $test->prop; +} + +function w($test) { + $test->prop = 0; + echo 'done'; +} + +function rw($test) { + $test->prop += 1; + echo 'done'; +} + +function im($test) { + $test->prop[] = 1; + echo 'done'; +} + +function is($test) { + echo (int) isset($test->prop); +} + +function us($test) { + unset($test->prop); + echo 'done'; +} + +foreach ([true, false] as $init) { + foreach ([true, false] as $scope) { + foreach (['r', 'w', 'rw', 'im', 'is', 'us'] as $op) { + $test = new Test(); + if ($init) { + $test->init(); + } + + echo 'Init: ' . ((int) $init) . ', scope: ' . ((int) $scope) . ', op: ' . $op . ": "; + try { + if ($scope) { + $test->{$op}(); + } else { + $op($test); + } + } catch (Error $e) { + echo $e->getMessage(); + } + echo "\n"; + } + } +} + +?> +--EXPECT-- +Init: 1, scope: 1, op: r: 1 +Init: 1, scope: 1, op: w: Cannot modify readonly property Test::$prop +Init: 1, scope: 1, op: rw: Cannot modify readonly property Test::$prop +Init: 1, scope: 1, op: im: Cannot modify readonly property Test::$prop +Init: 1, scope: 1, op: is: 1 +Init: 1, scope: 1, op: us: Cannot unset readonly property Test::$prop +Init: 1, scope: 0, op: r: 1 +Init: 1, scope: 0, op: w: Cannot modify readonly property Test::$prop +Init: 1, scope: 0, op: rw: Cannot modify readonly property Test::$prop +Init: 1, scope: 0, op: im: Cannot modify readonly property Test::$prop +Init: 1, scope: 0, op: is: 1 +Init: 1, scope: 0, op: us: Cannot unset readonly property Test::$prop +Init: 0, scope: 1, op: r: Typed property Test::$prop must not be accessed before initialization +Init: 0, scope: 1, op: w: done +Init: 0, scope: 1, op: rw: Typed property Test::$prop must not be accessed before initialization +Init: 0, scope: 1, op: im: Cannot indirectly modify readonly property Test::$prop +Init: 0, scope: 1, op: is: 0 +Init: 0, scope: 1, op: us: done +Init: 0, scope: 0, op: r: Typed property Test::$prop must not be accessed before initialization +Init: 0, scope: 0, op: w: Cannot initialize readonly property Test::$prop from global scope +Init: 0, scope: 0, op: rw: Typed property Test::$prop must not be accessed before initialization +Init: 0, scope: 0, op: im: Cannot indirectly modify readonly property Test::$prop +Init: 0, scope: 0, op: is: 0 +Init: 0, scope: 0, op: us: Cannot unset readonly property Test::$prop from global scope diff --git a/Zend/tests/readonly_props/variation_nested.phpt b/Zend/tests/readonly_props/variation_nested.phpt new file mode 100644 index 0000000000000..72a7925da9905 --- /dev/null +++ b/Zend/tests/readonly_props/variation_nested.phpt @@ -0,0 +1,77 @@ +--TEST-- +Readonly nested variations +--FILE-- +prop = new Inner(); + } +} + +function r($test) { + echo $test->prop->prop; +} + +function w($test) { + $test->prop->prop = 0; + echo 'done'; +} + +function rw($test) { + $test->prop->prop += 1; + echo 'done'; +} + +function im($test) { + $test->prop->array[] = 1; + echo 'done'; +} + +function is($test) { + echo (int) isset($test->prop->prop); +} + +function us($test) { + unset($test->prop->prop); + echo 'done'; +} + +foreach ([true, false] as $init) { + foreach (['r', 'w', 'rw', 'im', 'is', 'us'] as $op) { + $test = new Test(); + if ($init) { + $test->init(); + } + + echo 'Init: ' . ((int) $init) . ', op: ' . $op . ": "; + try { + $op($test); + } catch (Error $e) { + echo $e->getMessage(); + } + echo "\n"; + } +} + +?> +--EXPECT-- +Init: 1, op: r: 1 +Init: 1, op: w: done +Init: 1, op: rw: done +Init: 1, op: im: done +Init: 1, op: is: 1 +Init: 1, op: us: done +Init: 0, op: r: Typed property Test::$prop must not be accessed before initialization +Init: 0, op: w: Cannot indirectly modify readonly property Test::$prop +Init: 0, op: rw: Typed property Test::$prop must not be accessed before initialization +Init: 0, op: im: Cannot indirectly modify readonly property Test::$prop +Init: 0, op: is: 0 +Init: 0, op: us: done diff --git a/Zend/tests/traits/bug76773-deprecated.phpt b/Zend/tests/traits/bug76773-deprecated.phpt new file mode 100644 index 0000000000000..e6dac201fc758 --- /dev/null +++ b/Zend/tests/traits/bug76773-deprecated.phpt @@ -0,0 +1,35 @@ +--TEST-- +Bug #76773 (Traits used on the parent are ignored for child classes) [original test with deprecated syntax] +--FILE-- +hello(); +?> +--EXPECTF-- +ChildClass + +Deprecated: Use of "parent" in callables is deprecated in %s on line %d +ParentClass diff --git a/Zend/tests/traits/bug76773.phpt b/Zend/tests/traits/bug76773.phpt index 4ab53bf6d11d2..50b314794291d 100644 --- a/Zend/tests/traits/bug76773.phpt +++ b/Zend/tests/traits/bug76773.phpt @@ -9,7 +9,7 @@ trait MyTrait { echo __CLASS__, "\n"; - if (\is_callable(array('parent', __FUNCTION__))) { + if (get_parent_class(__CLASS__) !== false) { parent::hello(); } } diff --git a/Zend/tests/type_declarations/dnf_types/dnf_2_intersection.phpt b/Zend/tests/type_declarations/dnf_types/dnf_2_intersection.phpt new file mode 100644 index 0000000000000..6375c60ab71bb --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/dnf_2_intersection.phpt @@ -0,0 +1,63 @@ +--TEST-- +Union of two intersection type +--FILE-- +getMessage(), \PHP_EOL; +} +try { + bar2(); +} catch (\TypeError $e) { + echo $e->getMessage(), \PHP_EOL; +} + +?> +--EXPECTF-- +object(A)#%d (0) { +} +object(A)#%d (0) { +} +object(B)#%d (0) { +} +object(B)#%d (0) { +} +bar1(): Return value must be of type (X&Y)|(W&Z), C returned +bar2(): Return value must be of type (W&Z)|(X&Y), C returned diff --git a/Zend/tests/type_declarations/dnf_types/dnf_intersection_and_null.phpt b/Zend/tests/type_declarations/dnf_types/dnf_intersection_and_null.phpt new file mode 100644 index 0000000000000..e9089c130b492 --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/dnf_intersection_and_null.phpt @@ -0,0 +1,74 @@ +--TEST-- +Union of null and intersection type +--FILE-- +foo1($a); +$test->foo2($a); +$test->foo1($n); +$test->foo2($n); +$test->prop1 = $a; +$test->prop1 = $n; +$test->prop2 = $a; +$test->prop2 = $n; + +$c = new C(); +try { + $test->foo1($c); +} catch (\TypeError $e) { + echo $e->getMessage(), \PHP_EOL; +} +try { + $test->foo2($c); +} catch (\TypeError $e) { + echo $e->getMessage(), \PHP_EOL; +} +try { + $test->prop1 = $c; +} catch (\TypeError $e) { + echo $e->getMessage(), \PHP_EOL; +} +try { + $test->prop2 = $c; +} catch (\TypeError $e) { + echo $e->getMessage(), \PHP_EOL; +} + +?> +===DONE=== +--EXPECTF-- +object(A)#2 (0) { +} +object(A)#2 (0) { +} +NULL +NULL +Test::foo1(): Argument #1 ($v) must be of type (X&Y)|null, C given, called in %s on line %d +Test::foo2(): Argument #1 ($v) must be of type (X&Y)|null, C given, called in %s on line %d +Cannot assign C to property Test::$prop1 of type (X&Y)|null +Cannot assign C to property Test::$prop2 of type (X&Y)|null +===DONE=== diff --git a/Zend/tests/type_declarations/dnf_types/dnf_intersection_and_single.phpt b/Zend/tests/type_declarations/dnf_types/dnf_intersection_and_single.phpt new file mode 100644 index 0000000000000..4c9a5f95e30d0 --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/dnf_intersection_and_single.phpt @@ -0,0 +1,127 @@ +--TEST-- +Union of a simple and intersection type +--FILE-- +foo1($a); +$test->foo2($a); +$test->foo1($i); +$test->foo2($i); +$test->prop1 = $a; +$test->prop1 = $i; +$test->prop2 = $a; +$test->prop2 = $i; + +$test->bar1($a); +$test->bar2($a); +$test->bar1($b); +$test->bar2($b); +$test->prop3 = $a; +$test->prop4 = $b; +$test->prop3 = $a; +$test->prop4 = $b; + +$c = new C(); +try { + $test->foo1($c); +} catch (\TypeError $e) { + echo $e->getMessage(), \PHP_EOL; +} +try { + $test->foo2($c); +} catch (\TypeError $e) { + echo $e->getMessage(), \PHP_EOL; +} +try { + $test->bar1($c); +} catch (\TypeError $e) { + echo $e->getMessage(), \PHP_EOL; +} +try { + $test->bar2($c); +} catch (\TypeError $e) { + echo $e->getMessage(), \PHP_EOL; +} +try { + $test->prop1 = $c; +} catch (\TypeError $e) { + echo $e->getMessage(), \PHP_EOL; +} +try { + $test->prop2 = $c; +} catch (\TypeError $e) { + echo $e->getMessage(), \PHP_EOL; +} +try { + $test->prop3 = $c; +} catch (\TypeError $e) { + echo $e->getMessage(), \PHP_EOL; +} +try { + $test->prop4 = $c; +} catch (\TypeError $e) { + echo $e->getMessage(), \PHP_EOL; +} + +?> +===DONE=== +--EXPECTF-- +object(A)#2 (0) { +} +object(A)#2 (0) { +} +int(10) +int(10) +object(A)#2 (0) { +} +object(A)#2 (0) { +} +object(B)#3 (0) { +} +object(B)#3 (0) { +} +Test::foo1(): Argument #1 ($v) must be of type (X&Y)|int, C given, called in %s on line %d +Test::foo2(): Argument #1 ($v) must be of type (X&Y)|int, C given, called in %s on line %d +Test::bar1(): Argument #1 ($v) must be of type B|(X&Y), C given, called in %s on line %d +Test::bar2(): Argument #1 ($v) must be of type (X&Y)|B, C given, called in %s on line %d +Cannot assign C to property Test::$prop1 of type (X&Y)|int +Cannot assign C to property Test::$prop2 of type (X&Y)|int +Cannot assign C to property Test::$prop3 of type (X&Y)|B +Cannot assign C to property Test::$prop4 of type B|(X&Y) +===DONE=== diff --git a/Zend/tests/type_declarations/dnf_types/redundant_types/duplicate_class_alias_type.phpt b/Zend/tests/type_declarations/dnf_types/redundant_types/duplicate_class_alias_type.phpt new file mode 100644 index 0000000000000..93ff63856c0b2 --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/redundant_types/duplicate_class_alias_type.phpt @@ -0,0 +1,13 @@ +--TEST-- +Duplicate class alias type +--FILE-- + +--EXPECTF-- +Fatal error: Type X&A is redundant with type X&A in %s on line %d diff --git a/Zend/tests/type_declarations/dnf_types/redundant_types/duplicate_class_alias_type_runtime.phpt b/Zend/tests/type_declarations/dnf_types/redundant_types/duplicate_class_alias_type_runtime.phpt new file mode 100644 index 0000000000000..0b2e2a13d176c --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/redundant_types/duplicate_class_alias_type_runtime.phpt @@ -0,0 +1,15 @@ +--TEST-- +Duplicate class alias type at runtime +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/type_declarations/dnf_types/redundant_types/inheritence.phpt b/Zend/tests/type_declarations/dnf_types/redundant_types/inheritence.phpt new file mode 100644 index 0000000000000..ef57adf09c0e4 --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/redundant_types/inheritence.phpt @@ -0,0 +1,15 @@ +--TEST-- +Intersection with child class +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/type_declarations/dnf_types/redundant_types/less_restrive_type_constraint_already_present001.phpt b/Zend/tests/type_declarations/dnf_types/redundant_types/less_restrive_type_constraint_already_present001.phpt new file mode 100644 index 0000000000000..b0753313a99ea --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/redundant_types/less_restrive_type_constraint_already_present001.phpt @@ -0,0 +1,14 @@ +--TEST-- +A less restrictive type constrain is part of the DNF type 001 +--FILE-- + +===DONE=== +--EXPECTF-- +Fatal error: Type A&B is redundant as it is more restrictive than type A in %s on line %d diff --git a/Zend/tests/type_declarations/dnf_types/redundant_types/less_restrive_type_constraint_already_present002.phpt b/Zend/tests/type_declarations/dnf_types/redundant_types/less_restrive_type_constraint_already_present002.phpt new file mode 100644 index 0000000000000..6aa7ce16a4808 --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/redundant_types/less_restrive_type_constraint_already_present002.phpt @@ -0,0 +1,14 @@ +--TEST-- +A less restrictive type constrain is part of the DNF type 002 +--FILE-- + +===DONE=== +--EXPECTF-- +Fatal error: Type A&B is redundant as it is more restrictive than type A in %s on line %d diff --git a/Zend/tests/type_declarations/dnf_types/redundant_types/less_restrive_type_constraint_already_present003.phpt b/Zend/tests/type_declarations/dnf_types/redundant_types/less_restrive_type_constraint_already_present003.phpt new file mode 100644 index 0000000000000..55f248bc05e4f --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/redundant_types/less_restrive_type_constraint_already_present003.phpt @@ -0,0 +1,15 @@ +--TEST-- +A less restrictive type constrain is part of the DNF type 003 +--FILE-- + +===DONE=== +--EXPECTF-- +Fatal error: Type A&B&C is redundant as it is more restrictive than type A&B in %s on line %d diff --git a/Zend/tests/type_declarations/dnf_types/redundant_types/less_restrive_type_constraint_already_present004.phpt b/Zend/tests/type_declarations/dnf_types/redundant_types/less_restrive_type_constraint_already_present004.phpt new file mode 100644 index 0000000000000..ab69ebe9b5f64 --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/redundant_types/less_restrive_type_constraint_already_present004.phpt @@ -0,0 +1,15 @@ +--TEST-- +A less restrictive type constrain is part of the DNF type 004 +--FILE-- + +===DONE=== +--EXPECTF-- +Fatal error: Type A&B&C is redundant as it is more restrictive than type A&B in %s on line %d diff --git a/Zend/tests/type_declarations/dnf_types/variance/invalid1.phpt b/Zend/tests/type_declarations/dnf_types/variance/invalid1.phpt new file mode 100644 index 0000000000000..5e90cc7a79801 --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/variance/invalid1.phpt @@ -0,0 +1,28 @@ +--TEST-- +Co-variance check failure for intersection type where child replace one of intersection type members with a supertype +--FILE-- + +--EXPECTF-- +Fatal error: Declaration of FooChild::foo(): (A&C)|X must be compatible with Foo::foo(): (B&C)|X in %s on line %d diff --git a/Zend/tests/type_declarations/dnf_types/variance/invalid_covariance_drop_type1.phpt b/Zend/tests/type_declarations/dnf_types/variance/invalid_covariance_drop_type1.phpt new file mode 100644 index 0000000000000..9aaf44cad636c --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/variance/invalid_covariance_drop_type1.phpt @@ -0,0 +1,27 @@ +--TEST-- +Co-variance check failure for intersection type where child removes one of intersection type members +--FILE-- + +--EXPECTF-- +Fatal error: Declaration of FooChild::foo(): A|X must be compatible with Foo::foo(): (A&B)|X in %s on line %d diff --git a/Zend/tests/type_declarations/dnf_types/variance/invalid_covariance_drop_type2.phpt b/Zend/tests/type_declarations/dnf_types/variance/invalid_covariance_drop_type2.phpt new file mode 100644 index 0000000000000..67cd813007cb0 --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/variance/invalid_covariance_drop_type2.phpt @@ -0,0 +1,28 @@ +--TEST-- +Co-variance check failure for intersection type where child removes one of intersection type members +--FILE-- + +--EXPECTF-- +Fatal error: Declaration of FooChild::foo(): (A&B)|X must be compatible with Foo::foo(): (A&B&C)|X in %s on line %d diff --git a/Zend/tests/type_declarations/dnf_types/variance/invalid_covariance_intersection_to_union1.phpt b/Zend/tests/type_declarations/dnf_types/variance/invalid_covariance_intersection_to_union1.phpt new file mode 100644 index 0000000000000..273bbcf1ac500 --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/variance/invalid_covariance_intersection_to_union1.phpt @@ -0,0 +1,26 @@ +--TEST-- +Co-variance failure for intersection type where child is union, but not all members are a subtype of intersection 1 +--FILE-- + +--EXPECTF-- +Fatal error: Declaration of B::foo(): TestOne|TestTwo must be compatible with A::foo(): (X&Y)|L in %s on line %d diff --git a/Zend/tests/type_declarations/dnf_types/variance/invalid_covariance_intersection_to_union2.phpt b/Zend/tests/type_declarations/dnf_types/variance/invalid_covariance_intersection_to_union2.phpt new file mode 100644 index 0000000000000..1eafcb5d58718 --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/variance/invalid_covariance_intersection_to_union2.phpt @@ -0,0 +1,23 @@ +--TEST-- +Co-variance failure for intersection type where child is union, but not all members are a subtype of intersection 2 +--FILE-- + +--EXPECTF-- +Fatal error: Declaration of B::foo(): TestOne|int must be compatible with A::foo(): X&Y in %s on line %d diff --git a/Zend/tests/type_declarations/dnf_types/variance/invalid_covariance_intersection_to_union3.phpt b/Zend/tests/type_declarations/dnf_types/variance/invalid_covariance_intersection_to_union3.phpt new file mode 100644 index 0000000000000..c4dd3449f976d --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/variance/invalid_covariance_intersection_to_union3.phpt @@ -0,0 +1,25 @@ +--TEST-- +Co-variance failure for intersection type where child is union, but not all members are a subtype of intersection 2 +--FILE-- + +--EXPECTF-- +Fatal error: Declaration of B::foo(): TestOne|TestTwo must be compatible with A::foo(): X&Z in %s on line %d diff --git a/Zend/tests/type_declarations/dnf_types/variance/invalid_invariance1.phpt b/Zend/tests/type_declarations/dnf_types/variance/invalid_invariance1.phpt new file mode 100644 index 0000000000000..65d3d2033bbc1 --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/variance/invalid_invariance1.phpt @@ -0,0 +1,18 @@ +--TEST-- +Property types must be invariant +--FILE-- + +--EXPECTF-- +Fatal error: Type of B::$prop must be (X&Y)|L (as in class A) in %s on line %d diff --git a/Zend/tests/type_declarations/dnf_types/variance/invalid_invariance2.phpt b/Zend/tests/type_declarations/dnf_types/variance/invalid_invariance2.phpt new file mode 100644 index 0000000000000..3b82afa89355e --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/variance/invalid_invariance2.phpt @@ -0,0 +1,21 @@ +--TEST-- +Intersection type reduction invalid invariant type check +--FILE-- + +===DONE=== +--EXPECTF-- +Fatal error: Type of Test2::$prop must be (X&Y)|B (as in class Test) in %s on line %d diff --git a/Zend/tests/type_declarations/dnf_types/variance/valid1.phpt b/Zend/tests/type_declarations/dnf_types/variance/valid1.phpt new file mode 100644 index 0000000000000..3282b0f9dc04f --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/variance/valid1.phpt @@ -0,0 +1,40 @@ +--TEST-- +Valid inheritence - co-variance +--FILE-- +foo()); +$o = new FooSecondChild(); +var_dump($o->foo()); + +?> +--EXPECTF-- +object(Test)#%d (0) { +} +object(Test)#%d (0) { +} diff --git a/Zend/tests/type_declarations/dnf_types/variance/valid2.phpt b/Zend/tests/type_declarations/dnf_types/variance/valid2.phpt new file mode 100644 index 0000000000000..f77380326db96 --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/variance/valid2.phpt @@ -0,0 +1,23 @@ +--TEST-- +Commutative intersection types +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/type_declarations/dnf_types/variance/valid4.phpt b/Zend/tests/type_declarations/dnf_types/variance/valid4.phpt new file mode 100644 index 0000000000000..78691715c8e59 --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/variance/valid4.phpt @@ -0,0 +1,20 @@ +--TEST-- +Intersection type reduction valid invariant type check +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/type_declarations/dnf_types/variance/valid5.phpt b/Zend/tests/type_declarations/dnf_types/variance/valid5.phpt new file mode 100644 index 0000000000000..ca75aeb584f00 --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/variance/valid5.phpt @@ -0,0 +1,46 @@ +--TEST-- +Replacing union of classes respecting intersection type by intersection type +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/type_declarations/dnf_types/variance/valid6.phpt b/Zend/tests/type_declarations/dnf_types/variance/valid6.phpt new file mode 100644 index 0000000000000..faf63748aec34 --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/variance/valid6.phpt @@ -0,0 +1,20 @@ +--TEST-- +Replacing union type by intersection type +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/type_declarations/dnf_types/variance/valid7.phpt b/Zend/tests/type_declarations/dnf_types/variance/valid7.phpt new file mode 100644 index 0000000000000..3d9a58638e2f4 --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/variance/valid7.phpt @@ -0,0 +1,23 @@ +--TEST-- +Replacing object type with intersection type +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/type_declarations/dnf_types/variance/valid8.phpt b/Zend/tests/type_declarations/dnf_types/variance/valid8.phpt new file mode 100644 index 0000000000000..dda2fa94494ec --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/variance/valid8.phpt @@ -0,0 +1,20 @@ +--TEST-- +Covariant replacement of iterable type with intersection type in DNF type +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/type_declarations/dnf_types/variance/valid9.phpt b/Zend/tests/type_declarations/dnf_types/variance/valid9.phpt new file mode 100644 index 0000000000000..1061ca211954d --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/variance/valid9.phpt @@ -0,0 +1,18 @@ +--TEST-- +Covariant replacement of iterable type with unregistered intersection type in DNF type +--FILE-- + +===DONE=== +--EXPECTF-- +Fatal error: Could not check compatibility between Test2::method2(): (X&MyIterator)|int and Test::method2(): Traversable|array|int, because class X is not available in %s diff --git a/Zend/tests/type_declarations/typed_properties_095.phpt b/Zend/tests/type_declarations/typed_properties_095.phpt index a03bcf9555276..5caf862e72da7 100644 --- a/Zend/tests/type_declarations/typed_properties_095.phpt +++ b/Zend/tests/type_declarations/typed_properties_095.phpt @@ -2,6 +2,7 @@ Typed properties in internal classes --EXTENSIONS-- zend_test +spl --FILE-- NULL + ["classIntersectionProp"]=> + uninitialized(Traversable&Countable) ["readonlyProp"]=> uninitialized(int) } @@ -84,6 +87,8 @@ object(Test)#4 (3) { } ["classUnionProp"]=> NULL + ["classIntersectionProp"]=> + uninitialized(Traversable&Countable) ["readonlyProp"]=> uninitialized(int) } diff --git a/Zend/tests/weakrefs/weakmap_object_reference.phpt b/Zend/tests/weakrefs/weakmap_object_reference.phpt new file mode 100644 index 0000000000000..b291092fdb7f5 --- /dev/null +++ b/Zend/tests/weakrefs/weakmap_object_reference.phpt @@ -0,0 +1,32 @@ +--TEST-- +WeakMap object reference offset +--FILE-- + +--EXPECT-- +int(1) +object(WeakMap)#1 (1) { + [0]=> + array(2) { + ["key"]=> + object(stdClass)#2 (0) { + } + ["value"]=> + int(1) + } +} +bool(true) +bool(true) +int(1) diff --git a/Zend/tests/zend_ini_parse_quantity.phpt b/Zend/tests/zend_ini_parse_quantity.phpt new file mode 100644 index 0000000000000..09f0a731452b8 --- /dev/null +++ b/Zend/tests/zend_ini_parse_quantity.phpt @@ -0,0 +1,897 @@ +--TEST-- +Test parsing of quantities +--EXTENSIONS-- +zend_test +--FILE-- + '0', + 'No overflow 002' => '1', + 'No overflow 003' => '100', + 'No overflow 004' => strval(PHP_INT_MAX), + 'No overflow 005' => strval(PHP_INT_MIN), + 'No overflow 006' => '2K', + 'No overflow 007' => '-2K', + 'Subject overflow 001' => increment(strval(PHP_INT_MAX)), + 'Subject overflow 002' => decrement(strval(PHP_INT_MIN)), + 'Multiplier overflow 001' => strval(PHP_INT_MAX).'K', + 'Multiplier overflow 002' => strval(PHP_INT_MIN).'K', +]; + +foreach ($tests as $name => $value) { + printf("# %s: \"%s\"\n", $name, $value); + printf("%d\n", zend_test_zend_ini_parse_quantity($value)); + print "\n"; + print "----------\n"; +} + +--EXPECTF-- +# No overflow 001: "0" +0 + +---------- +# No overflow 002: "1" +1 + +---------- +# No overflow 003: "100" +100 + +---------- +# No overflow 004: "%d" +%d + +---------- +# No overflow 005: "-%d" +-%d + +---------- +# No overflow 006: "2K" +2048 + +---------- +# No overflow 007: "-2K" +-2048 + +---------- +# Subject overflow 001: "%d" + +Warning: Invalid quantity "%d": value is out of range, using overflow result for backwards compatibility in %s on line %d +%s + +---------- +# Subject overflow 002: "-%d" + +Warning: Invalid quantity "-%d": value is out of range, using overflow result for backwards compatibility in %s on line %d +%s + +---------- +# Multiplier overflow 001: "%dK" + +Warning: Invalid quantity "%dK": value is out of range, using overflow result for backwards compatibility in %s on line %d +%s + +---------- +# Multiplier overflow 002: "-%dK" + +Warning: Invalid quantity "-%dK": value is out of range, using overflow result for backwards compatibility in %s on line %d +%s + +---------- diff --git a/Zend/tests/zend_ini_parse_uquantity_overflow.phpt b/Zend/tests/zend_ini_parse_uquantity_overflow.phpt new file mode 100644 index 0000000000000..6dd3ed05076be --- /dev/null +++ b/Zend/tests/zend_ini_parse_uquantity_overflow.phpt @@ -0,0 +1,117 @@ +--TEST-- +Test zend_ini_parse_uquantity() overflow handling +--EXTENSIONS-- +zend_test +--FILE-- + '0', + 'No overflow 002' => '1', + 'No overflow 003' => '100', + 'No overflow 004' => strval(PHP_INT_MAX), + 'No overflow 005' => '2K', + 'No overflow 006' => '-1', + 'No overflow 007' => ' -1', + 'No overflow 008' => '-1 ', + 'No overflow 009' => ' -1 ', + 'Subject overflow 001' => base_convert(str_repeat('1', PHP_INT_SIZE*8+1), 2, 10), + 'Subject overflow 002' => '-'.base_convert(str_repeat('1', PHP_INT_SIZE*8+1), 2, 10), + 'Subject overflow 003' => strval(PHP_INT_MIN), + 'Subject overflow 004' => '-2', + 'Subject overflow 005' => '-1K', + 'Subject overflow 006' => '-1 K', + 'Multiplier overflow 001' => strval(PHP_INT_MAX).'K', +]; + +foreach ($tests as $name => $value) { + printf("# %s: \"%s\"\n", $name, $value); + printf("%u\n", zend_test_zend_ini_parse_uquantity($value)); + print "\n"; + print "----------\n"; +} + +printf("# zend_test_zend_ini_parse_uquantity(\"-1\") === -1\n"); +var_dump(zend_test_zend_ini_parse_uquantity("-1") === -1); + +--EXPECTF-- +# No overflow 001: "0" +0 + +---------- +# No overflow 002: "1" +1 + +---------- +# No overflow 003: "100" +100 + +---------- +# No overflow 004: "%d" +%d + +---------- +# No overflow 005: "2K" +2048 + +---------- +# No overflow 006: "-1" +%d + +---------- +# No overflow 007: " -1" +%d + +---------- +# No overflow 008: "-1 " +%d + +---------- +# No overflow 009: " -1 " +%d + +---------- +# Subject overflow 001: "%d" + +Warning: Invalid quantity "%d": value is out of range, using overflow result for backwards compatibility in %s on line %d +%d + +---------- +# Subject overflow 002: "-%d" + +Warning: Invalid quantity "-%d": value is out of range, using overflow result for backwards compatibility in %s on line %d +%d + +---------- +# Subject overflow 003: "-%d" + +Warning: Invalid quantity "-%d": value is out of range, using overflow result for backwards compatibility in %s on line %d +%d + +---------- +# Subject overflow 004: "-2" + +Warning: Invalid quantity "-2": value is out of range, using overflow result for backwards compatibility in %s on line %d +%d + +---------- +# Subject overflow 005: "-1K" + +Warning: Invalid quantity "-1K": value is out of range, using overflow result for backwards compatibility in %s on line %d +%d + +---------- +# Subject overflow 006: "-1 K" + +Warning: Invalid quantity "-1 K": value is out of range, using overflow result for backwards compatibility in %s on line %d +%d + +---------- +# Multiplier overflow 001: "%dK" + +Warning: Invalid quantity "%dK": value is out of range, using overflow result for backwards compatibility in %s on line %d +%d + +---------- +# zend_test_zend_ini_parse_uquantity("-1") === -1 +bool(true) diff --git a/Zend/zend.c b/Zend/zend.c index 97d937db5a2ed..6eeba07d7fac7 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -146,7 +146,7 @@ static ZEND_INI_MH(OnUpdateAssertions) /* {{{ */ { zend_long *p = (zend_long *) ZEND_INI_GET_ADDR(); - zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + zend_long val = zend_ini_parse_quantity_warn(new_value, entry->name); if (stage != ZEND_INI_STAGE_STARTUP && stage != ZEND_INI_STAGE_SHUTDOWN && @@ -176,7 +176,7 @@ static ZEND_INI_MH(OnSetExceptionStringParamMaxLen) /* {{{ */ static ZEND_INI_MH(OnUpdateFiberStackSize) /* {{{ */ { if (new_value) { - EG(fiber_stack_size) = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + EG(fiber_stack_size) = zend_ini_parse_quantity_warn(new_value, entry->name); } else { EG(fiber_stack_size) = ZEND_FIBER_DEFAULT_C_STACK_SIZE; } @@ -272,8 +272,7 @@ ZEND_API zend_string *zend_vstrpprintf(size_t max_len, const char *format, va_li ZSTR_LEN(buf.s) = max_len; } - smart_str_0(&buf); - return buf.s; + return smart_str_extract(&buf); } /* }}} */ @@ -1227,6 +1226,7 @@ ZEND_API void zend_activate(void) /* {{{ */ if (CG(map_ptr_last)) { memset(CG(map_ptr_real_base), 0, CG(map_ptr_last) * sizeof(void*)); } + zend_init_internal_run_time_cache(); zend_observer_activate(); } /* }}} */ diff --git a/Zend/zend.h b/Zend/zend.h index d58c02f4475b4..dc147f760ee0b 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -115,6 +115,7 @@ typedef struct _zend_class_mutable_data { zval *default_properties_table; HashTable *constants_table; uint32_t ce_flags; + HashTable *backed_enum_table; } zend_class_mutable_data; typedef struct _zend_class_dependency { diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 220b76efca6ff..90787376a6216 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -96,6 +96,14 @@ ZEND_API ZEND_COLD void zend_wrong_param_count(void) /* {{{ */ } /* }}} */ +ZEND_API ZEND_COLD void zend_wrong_property_read(zval *object, zval *property) +{ + zend_string *tmp_property_name; + zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name); + zend_error(E_WARNING, "Attempt to read property \"%s\" on %s", ZSTR_VAL(property_name), zend_zval_type_name(object)); + zend_tmp_string_release(tmp_property_name); +} + /* Argument parsing API -- andrei */ ZEND_API const char *zend_get_type_by_const(int type) /* {{{ */ { @@ -2686,6 +2694,11 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend internal_function->scope = scope; internal_function->prototype = NULL; internal_function->attributes = NULL; + if (EG(active)) { // at run-time: this ought to only happen if registered with dl() or somehow temporarily at runtime + ZEND_MAP_PTR_INIT(internal_function->run_time_cache, zend_arena_alloc(&CG(arena), zend_internal_run_time_cache_reserved_size())); + } else { + ZEND_MAP_PTR_NEW(internal_function->run_time_cache); + } if (ptr->flags) { if (!(ptr->flags & ZEND_ACC_PPP_MASK)) { if (ptr->flags != ZEND_ACC_DEPRECATED && scope) { @@ -2968,6 +2981,24 @@ static void clean_module_classes(int module_number) /* {{{ */ } /* }}} */ +static int clean_module_function(zval *el, void *arg) /* {{{ */ +{ + zend_function *fe = (zend_function *) Z_PTR_P(el); + zend_module_entry *module = (zend_module_entry *) arg; + if (fe->common.type == ZEND_INTERNAL_FUNCTION && fe->internal_function.module == module) { + return ZEND_HASH_APPLY_REMOVE; + } else { + return ZEND_HASH_APPLY_KEEP; + } +} +/* }}} */ + +static void clean_module_functions(zend_module_entry *module) /* {{{ */ +{ + zend_hash_apply_with_argument(CG(function_table), clean_module_function, module); +} +/* }}} */ + void module_destructor(zend_module_entry *module) /* {{{ */ { #if ZEND_RC_DEBUG @@ -3015,6 +3046,8 @@ void module_destructor(zend_module_entry *module) /* {{{ */ module->module_started=0; if (module->type == MODULE_TEMPORARY && module->functions) { zend_unregister_functions(module->functions, -1, NULL); + /* Clean functions registered separately from module->functions */ + clean_module_functions(module); } #if HAVE_LIBDL @@ -3392,7 +3425,7 @@ static bool zend_is_callable_check_class(zend_string *name, zend_class_entry *sc if (!scope) { if (error) *error = estrdup("cannot access \"self\" when no class scope is active"); } else { - if (error && !suppress_deprecation) { + if (!suppress_deprecation) { zend_error(E_DEPRECATED, "Use of \"self\" in callables is deprecated"); } fcc->called_scope = zend_get_called_scope(frame); @@ -3411,7 +3444,7 @@ static bool zend_is_callable_check_class(zend_string *name, zend_class_entry *sc } else if (!scope->parent) { if (error) *error = estrdup("cannot access \"parent\" when current class scope has no parent"); } else { - if (error && !suppress_deprecation) { + if (!suppress_deprecation) { zend_error(E_DEPRECATED, "Use of \"parent\" in callables is deprecated"); } fcc->called_scope = zend_get_called_scope(frame); @@ -3431,7 +3464,7 @@ static bool zend_is_callable_check_class(zend_string *name, zend_class_entry *sc if (!called_scope) { if (error) *error = estrdup("cannot access \"static\" when no class scope is active"); } else { - if (error && !suppress_deprecation) { + if (!suppress_deprecation) { zend_error(E_DEPRECATED, "Use of \"static\" in callables is deprecated"); } fcc->called_scope = called_scope; @@ -3480,7 +3513,7 @@ ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc) { } } -static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_execute_data *frame, zend_fcall_info_cache *fcc, bool strict_class, char **error) /* {{{ */ +static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_execute_data *frame, zend_fcall_info_cache *fcc, bool strict_class, char **error, bool suppress_deprecation) /* {{{ */ { zend_class_entry *ce_org = fcc->calling_scope; bool retval = 0; @@ -3566,7 +3599,7 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_ fcc->called_scope = fcc->object ? fcc->object->ce : fcc->calling_scope; } strict_class = 1; - } else if (!zend_is_callable_check_class(cname, scope, frame, fcc, &strict_class, error, ce_org != NULL)) { + } else if (!zend_is_callable_check_class(cname, scope, frame, fcc, &strict_class, error, suppress_deprecation || ce_org != NULL)) { zend_string_release_ex(cname, 0); return 0; } @@ -3577,7 +3610,7 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_ if (error) zend_spprintf(error, 0, "class %s is not a subclass of %s", ZSTR_VAL(ce_org->name), ZSTR_VAL(fcc->calling_scope->name)); return 0; } - if (ce_org && error) { + if (ce_org && !suppress_deprecation) { zend_error(E_DEPRECATED, "Callables of the form [\"%s\", \"%s\"] are deprecated", ZSTR_VAL(ce_org->name), Z_STRVAL_P(callable)); @@ -3818,7 +3851,7 @@ ZEND_API bool zend_is_callable_at_frame( } check_func: - ret = zend_is_callable_check_func(callable, frame, fcc, strict_class, error); + ret = zend_is_callable_check_func(callable, frame, fcc, strict_class, error, check_flags & IS_CALLABLE_SUPPRESS_DEPRECATIONS); if (fcc == &fcc_local) { zend_release_fcall_info_cache(fcc); } @@ -3855,7 +3888,7 @@ ZEND_API bool zend_is_callable_at_frame( return 1; } - if (!zend_is_callable_check_class(Z_STR_P(obj), get_scope(frame), frame, fcc, &strict_class, error, false)) { + if (!zend_is_callable_check_class(Z_STR_P(obj), get_scope(frame), frame, fcc, &strict_class, error, check_flags & IS_CALLABLE_SUPPRESS_DEPRECATIONS)) { return 0; } } else { @@ -3918,7 +3951,7 @@ ZEND_API bool zend_make_callable(zval *callable, zend_string **callable_name) /* { zend_fcall_info_cache fcc; - if (zend_is_callable_ex(callable, NULL, 0, callable_name, &fcc, NULL)) { + if (zend_is_callable_ex(callable, NULL, IS_CALLABLE_SUPPRESS_DEPRECATIONS, callable_name, &fcc, NULL)) { if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) { zval_ptr_dtor_str(callable); array_init(callable); @@ -4211,6 +4244,8 @@ ZEND_API zend_property_info *zend_declare_typed_property(zend_class_entry *ce, z if (is_persistent_class(ce)) { zend_type *single_type; ZEND_TYPE_FOREACH(property_info->type, single_type) { + // TODO Add support and test cases when gen_stub support added + ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*single_type)); if (ZEND_TYPE_HAS_NAME(*single_type)) { zend_string *name = zend_new_interned_string(ZEND_TYPE_NAME(*single_type)); ZEND_TYPE_SET_PTR(*single_type, name); diff --git a/Zend/zend_API.h b/Zend/zend_API.h index a2d4e60d7be0d..785a43191b208 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -321,6 +321,9 @@ typedef struct _zend_fcall_info_cache { #define CE_DEFAULT_PROPERTIES_TABLE(ce) \ zend_class_default_properties_table(ce) +#define CE_BACKED_ENUM_TABLE(ce) \ + zend_class_backed_enum_table(ce) + #define ZEND_FCI_INITIALIZED(fci) ((fci).size != 0) ZEND_API int zend_next_free_module(void); @@ -388,8 +391,10 @@ ZEND_API void zend_disable_functions(const char *function_list); ZEND_API zend_result zend_disable_class(const char *class_name, size_t class_name_length); ZEND_API ZEND_COLD void zend_wrong_param_count(void); +ZEND_API ZEND_COLD void zend_wrong_property_read(zval *object, zval *property); #define IS_CALLABLE_CHECK_SYNTAX_ONLY (1<<0) +#define IS_CALLABLE_SUPPRESS_DEPRECATIONS (1<<1) ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc); ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *object); @@ -450,6 +455,26 @@ static zend_always_inline zval *zend_class_default_properties_table(zend_class_e } } +static zend_always_inline void zend_class_set_backed_enum_table(zend_class_entry *ce, HashTable *backed_enum_table) +{ + if (ZEND_MAP_PTR(ce->mutable_data) && ce->type == ZEND_USER_CLASS) { + zend_class_mutable_data *mutable_data = (zend_class_mutable_data*)ZEND_MAP_PTR_GET_IMM(ce->mutable_data); + mutable_data->backed_enum_table = backed_enum_table; + } else { + ce->backed_enum_table = backed_enum_table; + } +} + +static zend_always_inline HashTable *zend_class_backed_enum_table(zend_class_entry *ce) +{ + if (ZEND_MAP_PTR(ce->mutable_data) && ce->type == ZEND_USER_CLASS) { + zend_class_mutable_data *mutable_data = (zend_class_mutable_data*)ZEND_MAP_PTR_GET_IMM(ce->mutable_data); + return mutable_data->backed_enum_table; + } else { + return ce->backed_enum_table; + } +} + ZEND_API void zend_update_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, zval *value); ZEND_API void zend_update_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zval *value); ZEND_API void zend_update_property_null(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length); @@ -714,7 +739,10 @@ static zend_always_inline zend_result zend_forbid_dynamic_call(void) ZEND_ASSERT(ex != NULL && ex->func != NULL); if (ZEND_CALL_INFO(ex) & ZEND_CALL_DYNAMIC) { - zend_throw_error(NULL, "Cannot call %s() dynamically", get_active_function_name()); + zend_string *function_or_method_name = get_active_function_or_method_name(); + zend_throw_error(NULL, "Cannot call %.*s() dynamically", + (int) ZSTR_LEN(function_or_method_name), ZSTR_VAL(function_or_method_name)); + zend_string_release(function_or_method_name); return FAILURE; } @@ -1316,8 +1344,8 @@ static zend_always_inline zval *zend_try_array_init(zval *zv) _(Z_EXPECTED_ARRAY_OR_NULL, "of type ?array") \ _(Z_EXPECTED_ARRAY_OR_LONG, "of type array|int") \ _(Z_EXPECTED_ARRAY_OR_LONG_OR_NULL, "of type array|int|null") \ - _(Z_EXPECTED_ITERABLE, "of type iterable") \ - _(Z_EXPECTED_ITERABLE_OR_NULL, "of type ?iterable") \ + _(Z_EXPECTED_ITERABLE, "of type Traversable|array") \ + _(Z_EXPECTED_ITERABLE_OR_NULL, "of type Traversable|array|null") \ _(Z_EXPECTED_FUNC, "a valid callback") \ _(Z_EXPECTED_FUNC_OR_NULL, "a valid callback or null") \ _(Z_EXPECTED_RESOURCE, "of type resource") \ @@ -1890,7 +1918,7 @@ ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char * Z_PARAM_VARIADIC_EX(spec, dest, dest_num, 0) #define Z_PARAM_VARIADIC_WITH_NAMED(dest, dest_num, dest_named) do { \ - int _num_varargs = _num_args - _i; \ + uint32_t _num_varargs = _num_args - _i; \ if (EXPECTED(_num_varargs > 0)) { \ dest = _real_arg + 1; \ dest_num = _num_varargs; \ diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 0ed2ee2a79aec..c7895a6624c60 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -57,6 +57,7 @@ #include "zend_operators.h" #include "zend_multiply.h" #include "zend_bitset.h" +#include "zend_mmap.h" #include #ifdef HAVE_UNISTD_H @@ -475,6 +476,7 @@ static void *zend_mm_mmap(size_t size) #endif ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, mflags, fd, 0); if (ptr != MAP_FAILED) { + zend_mmap_set_name(ptr, size, "zend_alloc"); return ptr; } } @@ -488,6 +490,7 @@ static void *zend_mm_mmap(size_t size) #endif return NULL; } + zend_mmap_set_name(ptr, size, "zend_alloc"); return ptr; #endif } @@ -989,9 +992,9 @@ static void *zend_mm_alloc_pages(zend_mm_heap *heap, uint32_t pages_count ZEND_F #if !ZEND_MM_LIMIT zend_mm_safe_error(heap, "Out of memory"); #elif ZEND_DEBUG - zend_mm_safe_error(heap, "Out of memory (allocated %zu) at %s:%d (tried to allocate %zu bytes)", heap->real_size, __zend_filename, __zend_lineno, size); + zend_mm_safe_error(heap, "Out of memory (allocated %zu bytes) at %s:%d (tried to allocate %zu bytes)", heap->real_size, __zend_filename, __zend_lineno, size); #else - zend_mm_safe_error(heap, "Out of memory (allocated %zu) (tried to allocate %zu bytes)", heap->real_size, ZEND_MM_PAGE_SIZE * pages_count); + zend_mm_safe_error(heap, "Out of memory (allocated %zu bytes) (tried to allocate %zu bytes)", heap->real_size, ZEND_MM_PAGE_SIZE * pages_count); #endif return NULL; } @@ -1807,9 +1810,9 @@ static void *zend_mm_alloc_huge(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D #if !ZEND_MM_LIMIT zend_mm_safe_error(heap, "Out of memory"); #elif ZEND_DEBUG - zend_mm_safe_error(heap, "Out of memory (allocated %zu) at %s:%d (tried to allocate %zu bytes)", heap->real_size, __zend_filename, __zend_lineno, size); + zend_mm_safe_error(heap, "Out of memory (allocated %zu bytes) at %s:%d (tried to allocate %zu bytes)", heap->real_size, __zend_filename, __zend_lineno, size); #else - zend_mm_safe_error(heap, "Out of memory (allocated %zu) (tried to allocate %zu bytes)", heap->real_size, size); + zend_mm_safe_error(heap, "Out of memory (allocated %zu bytes) (tried to allocate %zu bytes)", heap->real_size, size); #endif return NULL; } diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h index 9e10e6971f810..3df0a3ba719de 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -62,19 +62,19 @@ typedef struct _zend_mm_debug_info { BEGIN_EXTERN_C() -ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length) ZEND_ATTRIBUTE_MALLOC; +ZEND_API ZEND_ATTRIBUTE_MALLOC char* ZEND_FASTCALL zend_strndup(const char *s, size_t length); -ZEND_API void* ZEND_FASTCALL _emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1); -ZEND_API void* ZEND_FASTCALL _safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; -ZEND_API void* ZEND_FASTCALL _safe_malloc(size_t nmemb, size_t size, size_t offset) ZEND_ATTRIBUTE_MALLOC; +ZEND_API ZEND_ATTRIBUTE_MALLOC void* ZEND_FASTCALL _emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_ALLOC_SIZE(1); +ZEND_API ZEND_ATTRIBUTE_MALLOC void* ZEND_FASTCALL _safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); +ZEND_API ZEND_ATTRIBUTE_MALLOC void* ZEND_FASTCALL _safe_malloc(size_t nmemb, size_t size, size_t offset); ZEND_API void ZEND_FASTCALL _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); -ZEND_API void* ZEND_FASTCALL _ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE2(1,2); +ZEND_API ZEND_ATTRIBUTE_MALLOC void* ZEND_FASTCALL _ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_ALLOC_SIZE2(1,2); ZEND_API void* ZEND_FASTCALL _erealloc(void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_ALLOC_SIZE(2); ZEND_API void* ZEND_FASTCALL _erealloc2(void *ptr, size_t size, size_t copy_size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_ALLOC_SIZE(2); ZEND_API void* ZEND_FASTCALL _safe_erealloc(void *ptr, size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); ZEND_API void* ZEND_FASTCALL _safe_realloc(void *ptr, size_t nmemb, size_t size, size_t offset); -ZEND_API char* ZEND_FASTCALL _estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; -ZEND_API char* ZEND_FASTCALL _estrndup(const char *s, size_t length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; +ZEND_API ZEND_ATTRIBUTE_MALLOC char* ZEND_FASTCALL _estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); +ZEND_API ZEND_ATTRIBUTE_MALLOC char* ZEND_FASTCALL _estrndup(const char *s, size_t length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); ZEND_API size_t ZEND_FASTCALL _zend_mem_block_size(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); #include "zend_alloc_sizes.h" @@ -83,12 +83,12 @@ ZEND_API size_t ZEND_FASTCALL _zend_mem_block_size(void *ptr ZEND_FILE_LINE_DC Z #if !ZEND_DEBUG && defined(HAVE_BUILTIN_CONSTANT_P) # define _ZEND_BIN_ALLOCATOR_DEF(_num, _size, _elements, _pages, x, y) \ - ZEND_API void* ZEND_FASTCALL _emalloc_ ## _size(void) ZEND_ATTRIBUTE_MALLOC; + ZEND_API ZEND_ATTRIBUTE_MALLOC void* ZEND_FASTCALL _emalloc_ ## _size(void); ZEND_MM_BINS_INFO(_ZEND_BIN_ALLOCATOR_DEF, x, y) -ZEND_API void* ZEND_FASTCALL _emalloc_large(size_t size) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1); -ZEND_API void* ZEND_FASTCALL _emalloc_huge(size_t size) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1); +ZEND_API ZEND_ATTRIBUTE_MALLOC void* ZEND_FASTCALL _emalloc_large(size_t size) ZEND_ATTRIBUTE_ALLOC_SIZE(1); +ZEND_API ZEND_ATTRIBUTE_MALLOC void* ZEND_FASTCALL _emalloc_huge(size_t size) ZEND_ATTRIBUTE_ALLOC_SIZE(1); # define _ZEND_BIN_ALLOCATOR_SELECTOR_START(_num, _size, _elements, _pages, size, y) \ ((size <= _size) ? _emalloc_ ## _size() : @@ -179,8 +179,8 @@ ZEND_API void ZEND_FASTCALL _efree_huge(void *, size_t size); #define estrndup_rel(s, length) _estrndup((s), (length) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) #define zend_mem_block_size_rel(ptr) _zend_mem_block_size((ptr) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) -ZEND_API void * __zend_malloc(size_t len) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1); -ZEND_API void * __zend_calloc(size_t nmemb, size_t len) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE2(1,2); +ZEND_API ZEND_ATTRIBUTE_MALLOC void * __zend_malloc(size_t len) ZEND_ATTRIBUTE_ALLOC_SIZE(1); +ZEND_API ZEND_ATTRIBUTE_MALLOC void * __zend_calloc(size_t nmemb, size_t len) ZEND_ATTRIBUTE_ALLOC_SIZE2(1,2); ZEND_API void * __zend_realloc(void *p, size_t len) ZEND_ATTRIBUTE_ALLOC_SIZE(2); /* Selective persistent/non persistent allocation macros */ @@ -243,7 +243,7 @@ typedef struct _zend_mm_heap zend_mm_heap; ZEND_API zend_mm_heap *zend_mm_startup(void); ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, bool full_shutdown, bool silent); -ZEND_API void* ZEND_FASTCALL _zend_mm_alloc(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; +ZEND_API ZEND_ATTRIBUTE_MALLOC void* ZEND_FASTCALL _zend_mm_alloc(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_ALLOC_SIZE(2); ZEND_API void ZEND_FASTCALL _zend_mm_free(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); ZEND_API void* ZEND_FASTCALL _zend_mm_realloc(zend_mm_heap *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); ZEND_API void* ZEND_FASTCALL _zend_mm_realloc2(zend_mm_heap *heap, void *p, size_t size, size_t copy_size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 2c23421f9f3ef..9fbfcd4c202f7 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -498,10 +498,11 @@ zend_class_entry *zend_ast_fetch_class(zend_ast *ast, zend_class_entry *scope) return zend_fetch_class_with_scope(zend_ast_get_str(ast), ast->attr | ZEND_FETCH_CLASS_EXCEPTION, scope); } -ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope) +static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *ast, zend_class_entry *scope, bool *short_circuited_ptr) { zval op1, op2; zend_result ret = SUCCESS; + *short_circuited_ptr = false; switch (ast->kind) { case ZEND_AST_BINARY_OP: @@ -733,10 +734,16 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading"); } - if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) { + bool short_circuited; + if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited) != SUCCESS)) { ret = FAILURE; break; } + if (short_circuited) { + *short_circuited_ptr = true; + ZVAL_NULL(result); + return SUCCESS; + } // DIM on objects is disallowed because it allows executing arbitrary expressions if (Z_TYPE(op1) == IS_OBJECT) { @@ -907,6 +914,68 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast } return SUCCESS; } + case ZEND_AST_PROP: + case ZEND_AST_NULLSAFE_PROP: + { + bool short_circuited; + if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited) != SUCCESS)) { + return FAILURE; + } + if (short_circuited) { + *short_circuited_ptr = true; + ZVAL_NULL(result); + return SUCCESS; + } + if (ast->kind == ZEND_AST_NULLSAFE_PROP && Z_TYPE(op1) == IS_NULL) { + *short_circuited_ptr = true; + ZVAL_NULL(result); + return SUCCESS; + } + + if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) { + zval_ptr_dtor_nogc(&op1); + return FAILURE; + } + + if (!try_convert_to_string(&op2)) { + zval_ptr_dtor_nogc(&op1); + zval_ptr_dtor_nogc(&op2); + return FAILURE; + } + + if (Z_TYPE(op1) != IS_OBJECT) { + zend_wrong_property_read(&op1, &op2); + + zval_ptr_dtor_nogc(&op1); + zval_ptr_dtor_nogc(&op2); + + ZVAL_NULL(result); + return SUCCESS; + } + + zend_object *zobj = Z_OBJ(op1); + if (!(zobj->ce->ce_flags & ZEND_ACC_ENUM)) { + zend_throw_error(NULL, "Fetching properties on non-enums in constant expressions is not allowed"); + zval_ptr_dtor_nogc(&op1); + zval_ptr_dtor_nogc(&op2); + return FAILURE; + } + + zend_string *name = Z_STR(op2); + zval *property_result = zend_read_property_ex(scope, zobj, name, 0, result); + if (EG(exception)) { + zval_ptr_dtor_nogc(&op1); + zval_ptr_dtor_nogc(&op2); + return FAILURE; + } + + if (result != property_result) { + ZVAL_COPY(result, property_result); + } + zval_ptr_dtor_nogc(&op1); + zval_ptr_dtor_nogc(&op2); + return SUCCESS; + } default: zend_throw_error(NULL, "Unsupported constant expression"); ret = FAILURE; @@ -914,6 +983,12 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast return ret; } +ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope) +{ + bool short_circuited; + return zend_ast_evaluate_ex(result, ast, scope, &short_circuited); +} + static size_t ZEND_FASTCALL zend_ast_tree_size(zend_ast *ast) { size_t size; @@ -1686,9 +1761,12 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio } if (decl->child[2]) { if (decl->kind == ZEND_AST_ARROW_FUNC) { - ZEND_ASSERT(decl->child[2]->kind == ZEND_AST_RETURN); + zend_ast *body = decl->child[2]; + if (body->kind == ZEND_AST_RETURN) { + body = body->child[0]; + } smart_str_appends(str, " => "); - zend_ast_export_ex(str, decl->child[2]->child[0], 0, indent); + zend_ast_export_ex(str, body, 0, indent); break; } diff --git a/Zend/zend_atomic.h b/Zend/zend_atomic.h index 5f7f6fbc6e659..afc210e6336d5 100644 --- a/Zend/zend_atomic.h +++ b/Zend/zend_atomic.h @@ -150,7 +150,7 @@ static zend_always_inline bool zend_atomic_bool_load_ex(const zend_atomic_bool * static zend_always_inline bool zend_atomic_bool_exchange_ex(zend_atomic_bool *obj, bool desired) { bool prev = obj->value; - obj->value = true; + obj->value = desired; return prev; } diff --git a/Zend/zend_attributes.c b/Zend/zend_attributes.c index 6330887b29084..5a446c8c2859e 100644 --- a/Zend/zend_attributes.c +++ b/Zend/zend_attributes.c @@ -317,27 +317,39 @@ static void free_internal_attribute(zval *v) pefree(Z_PTR_P(v), 1); } -ZEND_API zend_internal_attribute *zend_internal_attribute_register(zend_class_entry *ce, uint32_t flags) +ZEND_API zend_internal_attribute *zend_mark_internal_attribute(zend_class_entry *ce) { zend_internal_attribute *internal_attr; + zend_attribute *attr; if (ce->type != ZEND_INTERNAL_CLASS) { zend_error_noreturn(E_ERROR, "Only internal classes can be registered as compiler attribute"); } - internal_attr = pemalloc(sizeof(zend_internal_attribute), 1); - internal_attr->ce = ce; - internal_attr->flags = flags; - internal_attr->validator = NULL; + ZEND_HASH_FOREACH_PTR(ce->attributes, attr) { + if (zend_string_equals(attr->name, zend_ce_attribute->name)) { + internal_attr = pemalloc(sizeof(zend_internal_attribute), 1); + internal_attr->ce = ce; + internal_attr->flags = Z_LVAL(attr->args[0].value); + internal_attr->validator = NULL; - zend_string *lcname = zend_string_tolower_ex(ce->name, 1); + zend_string *lcname = zend_string_tolower_ex(ce->name, 1); + zend_hash_update_ptr(&internal_attributes, lcname, internal_attr); + zend_string_release(lcname); - zend_hash_update_ptr(&internal_attributes, lcname, internal_attr); + return internal_attr; + } + } ZEND_HASH_FOREACH_END(); + + zend_error_noreturn(E_ERROR, "Classes must be first marked as attribute before being able to be registered as internal attribute class"); +} + +ZEND_API zend_internal_attribute *zend_internal_attribute_register(zend_class_entry *ce, uint32_t flags) +{ zend_attribute *attr = zend_add_class_attribute(ce, zend_ce_attribute->name, 1); ZVAL_LONG(&attr->args[0].value, flags); - zend_string_release(lcname); - return internal_attr; + return zend_mark_internal_attribute(ce); } ZEND_API zend_internal_attribute *zend_internal_attribute_get(zend_string *lcname) @@ -352,32 +364,23 @@ void zend_register_attribute_ce(void) zend_hash_init(&internal_attributes, 8, NULL, free_internal_attribute, 1); zend_ce_attribute = register_class_Attribute(); - attr = zend_internal_attribute_register(zend_ce_attribute, ZEND_ATTRIBUTE_TARGET_CLASS); + attr = zend_mark_internal_attribute(zend_ce_attribute); attr->validator = validate_attribute; - zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("TARGET_CLASS"), ZEND_ATTRIBUTE_TARGET_CLASS); - zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("TARGET_FUNCTION"), ZEND_ATTRIBUTE_TARGET_FUNCTION); - zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("TARGET_METHOD"), ZEND_ATTRIBUTE_TARGET_METHOD); - zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("TARGET_PROPERTY"), ZEND_ATTRIBUTE_TARGET_PROPERTY); - zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("TARGET_CLASS_CONSTANT"), ZEND_ATTRIBUTE_TARGET_CLASS_CONST); - zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("TARGET_PARAMETER"), ZEND_ATTRIBUTE_TARGET_PARAMETER); - zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("TARGET_ALL"), ZEND_ATTRIBUTE_TARGET_ALL); - zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("IS_REPEATABLE"), ZEND_ATTRIBUTE_IS_REPEATABLE); - zend_ce_return_type_will_change_attribute = register_class_ReturnTypeWillChange(); - zend_internal_attribute_register(zend_ce_return_type_will_change_attribute, ZEND_ATTRIBUTE_TARGET_METHOD); + zend_mark_internal_attribute(zend_ce_return_type_will_change_attribute); zend_ce_allow_dynamic_properties = register_class_AllowDynamicProperties(); - attr = zend_internal_attribute_register(zend_ce_allow_dynamic_properties, ZEND_ATTRIBUTE_TARGET_CLASS); + attr = zend_mark_internal_attribute(zend_ce_allow_dynamic_properties); attr->validator = validate_allow_dynamic_properties; zend_ce_sensitive_parameter = register_class_SensitiveParameter(); - attr = zend_internal_attribute_register(zend_ce_sensitive_parameter, ZEND_ATTRIBUTE_TARGET_PARAMETER); + zend_mark_internal_attribute(zend_ce_sensitive_parameter); memcpy(&attributes_object_handlers_sensitive_parameter_value, &std_object_handlers, sizeof(zend_object_handlers)); attributes_object_handlers_sensitive_parameter_value.get_properties_for = attributes_sensitive_parameter_value_get_properties_for; - /* This is not an actual attribute, thus the zend_internal_attribute_register() call is missing. */ + /* This is not an actual attribute, thus the zend_mark_internal_attribute() call is missing. */ zend_ce_sensitive_parameter_value = register_class_SensitiveParameterValue(); zend_ce_sensitive_parameter_value->create_object = attributes_sensitive_parameter_value_new; } diff --git a/Zend/zend_attributes.h b/Zend/zend_attributes.h index 6ffd3d89f94a0..fc02a7d656e25 100644 --- a/Zend/zend_attributes.h +++ b/Zend/zend_attributes.h @@ -77,6 +77,7 @@ ZEND_API zend_result zend_get_attribute_value(zval *ret, zend_attribute *attr, u ZEND_API zend_string *zend_get_attribute_target_names(uint32_t targets); ZEND_API bool zend_is_attribute_repeated(HashTable *attributes, zend_attribute *attr); +ZEND_API zend_internal_attribute *zend_mark_internal_attribute(zend_class_entry *ce); ZEND_API zend_internal_attribute *zend_internal_attribute_register(zend_class_entry *ce, uint32_t flags); ZEND_API zend_internal_attribute *zend_internal_attribute_get(zend_string *lcname); @@ -116,19 +117,6 @@ static zend_always_inline zend_attribute *zend_add_class_constant_attribute(zend return zend_add_attribute(&c->attributes, name, argc, flags, 0, 0); } -static zend_always_inline zend_attribute *zend_mark_function_parameter_as_sensitive(const HashTable *table, const char *func_name, uint32_t parameter) -{ - zend_function *func = zend_hash_str_find_ptr(table, func_name, strlen(func_name)); - ZEND_ASSERT(func != NULL); - - return zend_add_parameter_attribute( - func, - parameter, - zend_ce_sensitive_parameter->name, - 0 - ); -} - void zend_register_attribute_ce(void); void zend_attributes_shutdown(void); diff --git a/Zend/zend_attributes.stub.php b/Zend/zend_attributes.stub.php index 842ed9229cd6e..df13c9f82469f 100644 --- a/Zend/zend_attributes.stub.php +++ b/Zend/zend_attributes.stub.php @@ -2,18 +2,62 @@ /** @generate-class-entries */ +#[Attribute(Attribute::TARGET_CLASS)] final class Attribute { + /** + * @var int + * @cvalue ZEND_ATTRIBUTE_TARGET_CLASS + */ + const TARGET_CLASS = UNKNOWN; + /** + * @var int + * @cvalue ZEND_ATTRIBUTE_TARGET_FUNCTION + */ + const TARGET_FUNCTION = UNKNOWN; + /** + * @var int + * @cvalue ZEND_ATTRIBUTE_TARGET_METHOD + */ + const TARGET_METHOD = UNKNOWN; + /** + * @var int + * @cvalue ZEND_ATTRIBUTE_TARGET_PROPERTY + */ + const TARGET_PROPERTY = UNKNOWN; + /** + * @var int + * @cvalue ZEND_ATTRIBUTE_TARGET_CLASS_CONST + */ + const TARGET_CLASS_CONSTANT = UNKNOWN; + /** + * @var int + * @cvalue ZEND_ATTRIBUTE_TARGET_PARAMETER + */ + const TARGET_PARAMETER = UNKNOWN; + /** + * @var int + * @cvalue ZEND_ATTRIBUTE_TARGET_ALL + */ + const TARGET_ALL = UNKNOWN; + /** + * @var int + * @cvalue ZEND_ATTRIBUTE_IS_REPEATABLE + */ + const IS_REPEATABLE = UNKNOWN; + public int $flags; public function __construct(int $flags = Attribute::TARGET_ALL) {} } +#[Attribute(Attribute::TARGET_METHOD)] final class ReturnTypeWillChange { public function __construct() {} } +#[Attribute(Attribute::TARGET_CLASS)] final class AllowDynamicProperties { public function __construct() {} @@ -22,6 +66,7 @@ public function __construct() {} /** * @strict-properties */ +#[Attribute(Attribute::TARGET_PARAMETER)] final class SensitiveParameter { public function __construct() {} diff --git a/Zend/zend_attributes_arginfo.h b/Zend/zend_attributes_arginfo.h index 7c624949bf24b..3bcdcd707410c 100644 --- a/Zend/zend_attributes_arginfo.h +++ b/Zend/zend_attributes_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 5d9a092c1f0da5f32d9a161cc5166ed794ffe8e9 */ + * Stub hash: afb6a3f1d14099066d028b1579fff074359da293 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Attribute___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "Attribute::TARGET_ALL") @@ -71,12 +71,67 @@ static zend_class_entry *register_class_Attribute(void) class_entry = zend_register_internal_class_ex(&ce, NULL); class_entry->ce_flags |= ZEND_ACC_FINAL; + zval const_TARGET_CLASS_value; + ZVAL_LONG(&const_TARGET_CLASS_value, ZEND_ATTRIBUTE_TARGET_CLASS); + zend_string *const_TARGET_CLASS_name = zend_string_init_interned("TARGET_CLASS", sizeof("TARGET_CLASS") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_TARGET_CLASS_name, &const_TARGET_CLASS_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_TARGET_CLASS_name); + + zval const_TARGET_FUNCTION_value; + ZVAL_LONG(&const_TARGET_FUNCTION_value, ZEND_ATTRIBUTE_TARGET_FUNCTION); + zend_string *const_TARGET_FUNCTION_name = zend_string_init_interned("TARGET_FUNCTION", sizeof("TARGET_FUNCTION") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_TARGET_FUNCTION_name, &const_TARGET_FUNCTION_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_TARGET_FUNCTION_name); + + zval const_TARGET_METHOD_value; + ZVAL_LONG(&const_TARGET_METHOD_value, ZEND_ATTRIBUTE_TARGET_METHOD); + zend_string *const_TARGET_METHOD_name = zend_string_init_interned("TARGET_METHOD", sizeof("TARGET_METHOD") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_TARGET_METHOD_name, &const_TARGET_METHOD_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_TARGET_METHOD_name); + + zval const_TARGET_PROPERTY_value; + ZVAL_LONG(&const_TARGET_PROPERTY_value, ZEND_ATTRIBUTE_TARGET_PROPERTY); + zend_string *const_TARGET_PROPERTY_name = zend_string_init_interned("TARGET_PROPERTY", sizeof("TARGET_PROPERTY") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_TARGET_PROPERTY_name, &const_TARGET_PROPERTY_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_TARGET_PROPERTY_name); + + zval const_TARGET_CLASS_CONSTANT_value; + ZVAL_LONG(&const_TARGET_CLASS_CONSTANT_value, ZEND_ATTRIBUTE_TARGET_CLASS_CONST); + zend_string *const_TARGET_CLASS_CONSTANT_name = zend_string_init_interned("TARGET_CLASS_CONSTANT", sizeof("TARGET_CLASS_CONSTANT") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_TARGET_CLASS_CONSTANT_name, &const_TARGET_CLASS_CONSTANT_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_TARGET_CLASS_CONSTANT_name); + + zval const_TARGET_PARAMETER_value; + ZVAL_LONG(&const_TARGET_PARAMETER_value, ZEND_ATTRIBUTE_TARGET_PARAMETER); + zend_string *const_TARGET_PARAMETER_name = zend_string_init_interned("TARGET_PARAMETER", sizeof("TARGET_PARAMETER") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_TARGET_PARAMETER_name, &const_TARGET_PARAMETER_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_TARGET_PARAMETER_name); + + zval const_TARGET_ALL_value; + ZVAL_LONG(&const_TARGET_ALL_value, ZEND_ATTRIBUTE_TARGET_ALL); + zend_string *const_TARGET_ALL_name = zend_string_init_interned("TARGET_ALL", sizeof("TARGET_ALL") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_TARGET_ALL_name, &const_TARGET_ALL_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_TARGET_ALL_name); + + zval const_IS_REPEATABLE_value; + ZVAL_LONG(&const_IS_REPEATABLE_value, ZEND_ATTRIBUTE_IS_REPEATABLE); + zend_string *const_IS_REPEATABLE_name = zend_string_init_interned("IS_REPEATABLE", sizeof("IS_REPEATABLE") - 1, 1); + zend_declare_class_constant_ex(class_entry, const_IS_REPEATABLE_name, &const_IS_REPEATABLE_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_IS_REPEATABLE_name); + zval property_flags_default_value; ZVAL_UNDEF(&property_flags_default_value); zend_string *property_flags_name = zend_string_init("flags", sizeof("flags") - 1, 1); zend_declare_typed_property(class_entry, property_flags_name, &property_flags_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); zend_string_release(property_flags_name); + zend_string *attribute_name_Attribute_class_Attribute = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_Attribute = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_Attribute, 1); + zend_string_release(attribute_name_Attribute_class_Attribute); + zval attribute_Attribute_class_Attribute_arg0; + ZVAL_LONG(&attribute_Attribute_class_Attribute_arg0, ZEND_ATTRIBUTE_TARGET_CLASS); + ZVAL_COPY_VALUE(&attribute_Attribute_class_Attribute->args[0].value, &attribute_Attribute_class_Attribute_arg0); + return class_entry; } @@ -88,6 +143,13 @@ static zend_class_entry *register_class_ReturnTypeWillChange(void) class_entry = zend_register_internal_class_ex(&ce, NULL); class_entry->ce_flags |= ZEND_ACC_FINAL; + zend_string *attribute_name_Attribute_class_ReturnTypeWillChange = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_ReturnTypeWillChange = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ReturnTypeWillChange, 1); + zend_string_release(attribute_name_Attribute_class_ReturnTypeWillChange); + zval attribute_Attribute_class_ReturnTypeWillChange_arg0; + ZVAL_LONG(&attribute_Attribute_class_ReturnTypeWillChange_arg0, ZEND_ATTRIBUTE_TARGET_METHOD); + ZVAL_COPY_VALUE(&attribute_Attribute_class_ReturnTypeWillChange->args[0].value, &attribute_Attribute_class_ReturnTypeWillChange_arg0); + return class_entry; } @@ -99,6 +161,13 @@ static zend_class_entry *register_class_AllowDynamicProperties(void) class_entry = zend_register_internal_class_ex(&ce, NULL); class_entry->ce_flags |= ZEND_ACC_FINAL; + zend_string *attribute_name_Attribute_class_AllowDynamicProperties = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_AllowDynamicProperties = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_AllowDynamicProperties, 1); + zend_string_release(attribute_name_Attribute_class_AllowDynamicProperties); + zval attribute_Attribute_class_AllowDynamicProperties_arg0; + ZVAL_LONG(&attribute_Attribute_class_AllowDynamicProperties_arg0, ZEND_ATTRIBUTE_TARGET_CLASS); + ZVAL_COPY_VALUE(&attribute_Attribute_class_AllowDynamicProperties->args[0].value, &attribute_Attribute_class_AllowDynamicProperties_arg0); + return class_entry; } @@ -110,6 +179,13 @@ static zend_class_entry *register_class_SensitiveParameter(void) class_entry = zend_register_internal_class_ex(&ce, NULL); class_entry->ce_flags |= ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES; + zend_string *attribute_name_Attribute_class_SensitiveParameter = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_SensitiveParameter = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_SensitiveParameter, 1); + zend_string_release(attribute_name_Attribute_class_SensitiveParameter); + zval attribute_Attribute_class_SensitiveParameter_arg0; + ZVAL_LONG(&attribute_Attribute_class_SensitiveParameter_arg0, ZEND_ATTRIBUTE_TARGET_PARAMETER); + ZVAL_COPY_VALUE(&attribute_Attribute_class_SensitiveParameter->args[0].value, &attribute_Attribute_class_SensitiveParameter_arg0); + return class_entry; } diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 963332e0f7ed8..8813fa9788a97 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -38,8 +38,6 @@ ZEND_MINIT_FUNCTION(core) { /* {{{ */ zend_register_default_classes(); zend_standard_class_def = register_class_stdClass(); - zend_add_class_attribute(zend_standard_class_def, zend_ce_allow_dynamic_properties->name, 0); - zend_standard_class_def->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES; return SUCCESS; } diff --git a/Zend/zend_builtin_functions.stub.php b/Zend/zend_builtin_functions.stub.php index 20acca3a47ff7..ca04719742c54 100644 --- a/Zend/zend_builtin_functions.stub.php +++ b/Zend/zend_builtin_functions.stub.php @@ -2,6 +2,7 @@ /** @generate-class-entries */ +#[\AllowDynamicProperties] class stdClass { } @@ -102,14 +103,12 @@ function user_error(string $message, int $error_level = E_USER_NOTICE): bool {} /** @return callable|null */ function set_error_handler(?callable $callback, int $error_levels = E_ALL) {} -/** @return true */ -function restore_error_handler(): bool {} +function restore_error_handler(): true {} /** @return callable|null */ function set_exception_handler(?callable $callback) {} -/** @return true */ -function restore_exception_handler(): bool {} +function restore_exception_handler(): true {} /** * @return array diff --git a/Zend/zend_builtin_functions_arginfo.h b/Zend/zend_builtin_functions_arginfo.h index 37ea1f7aab1b3..838084418871c 100644 --- a/Zend/zend_builtin_functions_arginfo.h +++ b/Zend/zend_builtin_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 69dcb08ae12b6acbba872f7de5018ca5c0aaf669 */ + * Stub hash: 80355bb52d643177e3a661a515d9ea915bd1e2fc */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_version, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -139,7 +139,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_set_error_handler, 0, 0, 1) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, error_levels, IS_LONG, 0, "E_ALL") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_restore_error_handler, 0, 0, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_restore_error_handler, 0, 0, IS_TRUE, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_set_exception_handler, 0, 0, 1) @@ -207,7 +207,8 @@ ZEND_END_ARG_INFO() #define arginfo_gc_collect_cycles arginfo_func_num_args -#define arginfo_gc_enabled arginfo_restore_error_handler +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gc_enabled, 0, 0, _IS_BOOL, 0) +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gc_enable, 0, 0, IS_VOID, 0) ZEND_END_ARG_INFO() @@ -352,6 +353,11 @@ static zend_class_entry *register_class_stdClass(void) INIT_CLASS_ENTRY(ce, "stdClass", class_stdClass_methods); class_entry = zend_register_internal_class_ex(&ce, NULL); + class_entry->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES; + + zend_string *attribute_name_AllowDynamicProperties_class_stdClass = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, 1); + zend_add_class_attribute(class_entry, attribute_name_AllowDynamicProperties_class_stdClass, 0); + zend_string_release(attribute_name_AllowDynamicProperties_class_stdClass); return class_entry; } diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index e141d0956dc95..3a2c3b11d385c 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -121,7 +121,6 @@ ZEND_METHOD(Closure, call) zend_closure *closure; zend_fcall_info fci; zend_fcall_info_cache fci_cache; - zend_function my_function; zend_object *newobj; zend_class_entry *newclass; @@ -142,55 +141,71 @@ ZEND_METHOD(Closure, call) return; } + fci_cache.called_scope = newclass; + fci_cache.object = fci.object = newobj; + + fci.size = sizeof(fci); + ZVAL_OBJ(&fci.function_name, &closure->std); + ZVAL_UNDEF(&closure_result); + fci.retval = &closure_result; + if (closure->func.common.fn_flags & ZEND_ACC_GENERATOR) { zval new_closure; zend_create_closure(&new_closure, &closure->func, newclass, closure->called_scope, newthis); closure = (zend_closure *) Z_OBJ(new_closure); fci_cache.function_handler = &closure->func; + + zend_call_function(&fci, &fci_cache); + + /* copied upon generator creation */ + GC_DELREF(&closure->std); } else { - memcpy(&my_function, &closure->func, closure->func.type == ZEND_USER_FUNCTION ? sizeof(zend_op_array) : sizeof(zend_internal_function)); - my_function.common.fn_flags &= ~ZEND_ACC_CLOSURE; + zend_function *my_function; + if (ZEND_USER_CODE(closure->func.type)) { + my_function = emalloc(sizeof(zend_op_array)); + memcpy(my_function, &closure->func, sizeof(zend_op_array)); + } else { + my_function = emalloc(sizeof(zend_internal_function)); + memcpy(my_function, &closure->func, sizeof(zend_internal_function)); + } + my_function->common.fn_flags &= ~ZEND_ACC_CLOSURE; /* use scope of passed object */ - my_function.common.scope = newclass; + my_function->common.scope = newclass; if (closure->func.type == ZEND_INTERNAL_FUNCTION) { - my_function.internal_function.handler = closure->orig_internal_handler; + my_function->internal_function.handler = closure->orig_internal_handler; } - fci_cache.function_handler = &my_function; + fci_cache.function_handler = my_function; /* Runtime cache relies on bound scope to be immutable, hence we need a separate rt cache in case scope changed */ - if (ZEND_USER_CODE(my_function.type) + if (ZEND_USER_CODE(my_function->type) && (closure->func.common.scope != newclass || (closure->func.common.fn_flags & ZEND_ACC_HEAP_RT_CACHE))) { void *ptr; - my_function.op_array.fn_flags |= ZEND_ACC_HEAP_RT_CACHE; - ptr = emalloc(my_function.op_array.cache_size); - ZEND_MAP_PTR_INIT(my_function.op_array.run_time_cache, ptr); - memset(ptr, 0, my_function.op_array.cache_size); + my_function->op_array.fn_flags |= ZEND_ACC_HEAP_RT_CACHE; + ptr = emalloc(my_function->op_array.cache_size); + ZEND_MAP_PTR_INIT(my_function->op_array.run_time_cache, ptr); + memset(ptr, 0, my_function->op_array.cache_size); } - } - fci_cache.called_scope = newclass; - fci_cache.object = fci.object = newobj; + zend_call_function(&fci, &fci_cache); - fci.size = sizeof(fci); - ZVAL_OBJ(&fci.function_name, &closure->std); - fci.retval = &closure_result; + if (ZEND_USER_CODE(my_function->type)) { + if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_HEAP_RT_CACHE) { + efree(ZEND_MAP_PTR(my_function->op_array.run_time_cache)); + } + efree_size(my_function, sizeof(zend_op_array)); + } else { + efree_size(my_function, sizeof(zend_internal_function)); + } + } - if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(closure_result) != IS_UNDEF) { + if (Z_TYPE(closure_result) != IS_UNDEF) { if (Z_ISREF(closure_result)) { zend_unwrap_reference(&closure_result); } ZVAL_COPY_VALUE(return_value, &closure_result); } - - if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_GENERATOR) { - /* copied upon generator creation */ - GC_DELREF(&closure->std); - } else if (ZEND_USER_CODE(my_function.type) - && (fci_cache.function_handler->common.fn_flags & ZEND_ACC_HEAP_RT_CACHE)) { - efree(ZEND_MAP_PTR(my_function.op_array.run_time_cache)); - } } /* }}} */ @@ -523,7 +538,7 @@ static zend_object *zend_closure_clone(zend_object *zobject) /* {{{ */ } /* }}} */ -int zend_closure_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only) /* {{{ */ +static zend_result zend_closure_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only) /* {{{ */ { zend_closure *closure = (zend_closure*)obj; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 728feded60896..2467c92b514c4 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -33,6 +33,7 @@ #include "zend_inheritance.h" #include "zend_vm.h" #include "zend_enum.h" +#include "zend_observer.h" #define SET_NODE(target, src) do { \ target ## _type = (src)->op_type; \ @@ -1192,16 +1193,54 @@ static zend_string *resolve_class_name(zend_string *name, zend_class_entry *scop return zend_string_copy(name); } +static zend_string *add_intersection_type(zend_string *str, + zend_type_list *intersection_type_list, zend_class_entry *scope, + bool is_bracketed) +{ + zend_type *single_type; + zend_string *intersection_str = NULL; + + ZEND_TYPE_LIST_FOREACH(intersection_type_list, single_type) { + ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*single_type)); + ZEND_ASSERT(ZEND_TYPE_HAS_NAME(*single_type)); + zend_string *name = ZEND_TYPE_NAME(*single_type); + zend_string *resolved = resolve_class_name(name, scope); + intersection_str = add_type_string(intersection_str, resolved, /* is_intersection */ true); + zend_string_release(resolved); + } ZEND_TYPE_LIST_FOREACH_END(); + + ZEND_ASSERT(intersection_str); + + if (is_bracketed) { + zend_string *result = zend_string_concat3("(", 1, ZSTR_VAL(intersection_str), ZSTR_LEN(intersection_str), ")", 1); + zend_string_release(intersection_str); + intersection_str = result; + } + str = add_type_string(str, intersection_str, /* is_intersection */ false); + zend_string_release(intersection_str); + return str; +} + zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scope) { zend_string *str = NULL; - if (ZEND_TYPE_HAS_LIST(type)) { + /* Pure intersection type */ + if (ZEND_TYPE_IS_INTERSECTION(type)) { + ZEND_ASSERT(!ZEND_TYPE_IS_UNION(type)); + str = add_intersection_type(str, ZEND_TYPE_LIST(type), scope, /* is_bracketed */ false); + } else if (ZEND_TYPE_HAS_LIST(type)) { + /* A union type might not be a list */ zend_type *list_type; - bool is_intersection = ZEND_TYPE_IS_INTERSECTION(type); ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) { + if (ZEND_TYPE_IS_INTERSECTION(*list_type)) { + str = add_intersection_type(str, ZEND_TYPE_LIST(*list_type), scope, /* is_bracketed */ true); + continue; + } + ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type)); + ZEND_ASSERT(ZEND_TYPE_HAS_NAME(*list_type)); zend_string *name = ZEND_TYPE_NAME(*list_type); zend_string *resolved = resolve_class_name(name, scope); - str = add_type_string(str, resolved, is_intersection); + str = add_type_string(str, resolved, /* is_intersection */ false); zend_string_release(resolved); } ZEND_TYPE_LIST_FOREACH_END(); } else if (ZEND_TYPE_HAS_NAME(type)) { @@ -1259,7 +1298,8 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop if (type_mask & MAY_BE_NULL) { bool is_union = !str || memchr(ZSTR_VAL(str), '|', ZSTR_LEN(str)) != NULL; - if (!is_union) { + bool has_intersection = !str || memchr(ZSTR_VAL(str), '&', ZSTR_LEN(str)) != NULL; + if (!is_union && !has_intersection) { zend_string *nullable_str = zend_string_concat2("?", 1, ZSTR_VAL(str), ZSTR_LEN(str)); zend_string_release(str); return nullable_str; @@ -3623,7 +3663,7 @@ ZEND_API zend_uchar zend_get_call_op(const zend_op *init_op, zend_function *fbc) } /* }}} */ -static bool zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc) /* {{{ */ +static bool zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc, uint32_t lineno) /* {{{ */ { zend_op *opline; uint32_t opnum_init = get_next_op_number() - 1; @@ -3660,6 +3700,7 @@ static bool zend_compile_call_common(znode *result, zend_ast *args_ast, zend_fun if (may_have_extra_named_args) { opline->extended_value = ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS; } + opline->lineno = lineno; zend_do_extended_fcall_end(); return false; } @@ -3678,7 +3719,7 @@ static bool zend_compile_function_name(znode *name_node, zend_ast *name_ast) /* } /* }}} */ -static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast) /* {{{ */ +static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast, uint32_t lineno) /* {{{ */ { zend_op *opline = get_next_op(); opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME; @@ -3687,11 +3728,11 @@ static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args Z_STR(name_node->u.constant)); opline->result.num = zend_alloc_cache_slot(); - zend_compile_call_common(result, args_ast, NULL); + zend_compile_call_common(result, args_ast, NULL, lineno); } /* }}} */ -static void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast) /* {{{ */ +static void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast, uint32_t lineno) /* {{{ */ { if (name_node->op_type == IS_CONST && Z_TYPE(name_node->u.constant) == IS_STRING) { const char *colon; @@ -3721,7 +3762,7 @@ static void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast zend_emit_op(NULL, ZEND_INIT_DYNAMIC_CALL, NULL, name_node); } - zend_compile_call_common(result, args_ast, NULL); + zend_compile_call_common(result, args_ast, NULL, lineno); } /* }}} */ @@ -4015,7 +4056,7 @@ static zend_result zend_compile_func_cuf(znode *result, zend_ast_list *args, zen } /* }}} */ -static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string *name, zend_function *fbc) /* {{{ */ +static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string *name, zend_function *fbc, uint32_t lineno) /* {{{ */ { if (EG(assertions) >= 0) { znode name_node; @@ -4050,7 +4091,7 @@ static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string zend_ast_list_add((zend_ast *) args, arg); } - zend_compile_call_common(result, (zend_ast*)args, fbc); + zend_compile_call_common(result, (zend_ast*)args, fbc, lineno); opline = &CG(active_op_array)->opcodes[check_op_number]; opline->op2.opline_num = get_next_op_number(); @@ -4377,7 +4418,7 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{ if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) { zend_compile_expr(&name_node, name_ast); - zend_compile_dynamic_call(result, &name_node, args_ast); + zend_compile_dynamic_call(result, &name_node, args_ast, ast->lineno); return; } @@ -4386,9 +4427,9 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{ if (runtime_resolution) { if (zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "assert") && !is_callable_convert) { - zend_compile_assert(result, zend_ast_get_list(args_ast), Z_STR(name_node.u.constant), NULL); + zend_compile_assert(result, zend_ast_get_list(args_ast), Z_STR(name_node.u.constant), NULL, ast->lineno); } else { - zend_compile_ns_call(result, &name_node, args_ast); + zend_compile_ns_call(result, &name_node, args_ast, ast->lineno); } return; } @@ -4405,7 +4446,7 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{ /* Special assert() handling should apply independently of compiler flags. */ if (fbc && zend_string_equals_literal(lcname, "assert") && !is_callable_convert) { - zend_compile_assert(result, zend_ast_get_list(args_ast), lcname, fbc); + zend_compile_assert(result, zend_ast_get_list(args_ast), lcname, fbc, ast->lineno); zend_string_release(lcname); zval_ptr_dtor(&name_node.u.constant); return; @@ -4417,7 +4458,7 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{ || (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) && fbc->op_array.filename != CG(active_op_array)->filename) ) { zend_string_release_ex(lcname, 0); - zend_compile_dynamic_call(result, &name_node, args_ast); + zend_compile_dynamic_call(result, &name_node, args_ast, ast->lineno); return; } @@ -4436,7 +4477,7 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{ opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node); opline->result.num = zend_alloc_cache_slot(); - zend_compile_call_common(result, args_ast, fbc); + zend_compile_call_common(result, args_ast, fbc, ast->lineno); } } /* }}} */ @@ -4500,7 +4541,7 @@ static void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type } } - if (zend_compile_call_common(result, args_ast, fbc)) { + if (zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast))) { if (short_circuiting_checkpoint != zend_short_circuiting_checkpoint()) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot combine nullsafe operator with Closure creation"); @@ -4597,7 +4638,7 @@ static void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type } } - zend_compile_call_common(result, args_ast, fbc); + zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast)); } /* }}} */ @@ -4629,7 +4670,7 @@ static void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */ SET_NODE(opline->op1, &class_node); } - zend_compile_call_common(&ctor_result, args_ast, NULL); + zend_compile_call_common(&ctor_result, args_ast, NULL, ast->lineno); zend_do_free(&ctor_result); } /* }}} */ @@ -6197,6 +6238,88 @@ static zend_type zend_compile_single_typename(zend_ast *ast) } } +static void zend_are_intersection_types_redundant(zend_type left_type, zend_type right_type) +{ + ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(left_type)); + ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(right_type)); + zend_type_list *l_type_list = ZEND_TYPE_LIST(left_type); + zend_type_list *r_type_list = ZEND_TYPE_LIST(right_type); + zend_type_list *smaller_type_list, *larger_type_list; + bool flipped = false; + + if (r_type_list->num_types < l_type_list->num_types) { + smaller_type_list = r_type_list; + larger_type_list = l_type_list; + flipped = true; + } else { + smaller_type_list = l_type_list; + larger_type_list = r_type_list; + } + + unsigned int sum = 0; + zend_type *outer_type; + ZEND_TYPE_LIST_FOREACH(smaller_type_list, outer_type) + zend_type *inner_type; + ZEND_TYPE_LIST_FOREACH(larger_type_list, inner_type) + if (zend_string_equals_ci(ZEND_TYPE_NAME(*inner_type), ZEND_TYPE_NAME(*outer_type))) { + sum++; + break; + } + ZEND_TYPE_LIST_FOREACH_END(); + ZEND_TYPE_LIST_FOREACH_END(); + + if (sum == smaller_type_list->num_types) { + zend_string *smaller_type_str; + zend_string *larger_type_str; + if (flipped) { + smaller_type_str = zend_type_to_string(right_type); + larger_type_str = zend_type_to_string(left_type); + } else { + smaller_type_str = zend_type_to_string(left_type); + larger_type_str = zend_type_to_string(right_type); + } + if (smaller_type_list->num_types == larger_type_list->num_types) { + zend_error_noreturn(E_COMPILE_ERROR, "Type %s is redundant with type %s", + ZSTR_VAL(smaller_type_str), ZSTR_VAL(larger_type_str)); + } else { + zend_error_noreturn(E_COMPILE_ERROR, "Type %s is redundant as it is more restrictive than type %s", + ZSTR_VAL(larger_type_str), ZSTR_VAL(smaller_type_str)); + } + } +} + +static void zend_is_intersection_type_redundant_by_single_type(zend_type intersection_type, zend_type single_type) +{ + ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(intersection_type)); + ZEND_ASSERT(!ZEND_TYPE_IS_INTERSECTION(single_type)); + + zend_type *single_intersection_type = NULL; + ZEND_TYPE_FOREACH(intersection_type, single_intersection_type) + if (zend_string_equals_ci(ZEND_TYPE_NAME(*single_intersection_type), ZEND_TYPE_NAME(single_type))) { + zend_string *single_type_str = zend_type_to_string(single_type); + zend_string *complete_type = zend_type_to_string(intersection_type); + zend_error_noreturn(E_COMPILE_ERROR, "Type %s is redundant as it is more restrictive than type %s", + ZSTR_VAL(complete_type), ZSTR_VAL(single_type_str)); + } + ZEND_TYPE_FOREACH_END(); +} + +/* Used by both intersection and union types prior to transforming the type list to a full zend_type */ +static void zend_is_type_list_redundant_by_single_type(zend_type_list *type_list, zend_type type) +{ + ZEND_ASSERT(!ZEND_TYPE_IS_INTERSECTION(type)); + for (size_t i = 0; i < type_list->num_types - 1; i++) { + if (ZEND_TYPE_IS_INTERSECTION(type_list->types[i])) { + zend_is_intersection_type_redundant_by_single_type(type_list->types[i], type); + continue; + } + if (zend_string_equals_ci(ZEND_TYPE_NAME(type_list->types[i]), ZEND_TYPE_NAME(type))) { + zend_string *single_type_str = zend_type_to_string(type); + zend_error_noreturn(E_COMPILE_ERROR, "Duplicate type %s is redundant", ZSTR_VAL(single_type_str)); + } + } +} + static zend_type zend_compile_typename( zend_ast *ast, bool force_allow_null) /* {{{ */ { @@ -6211,6 +6334,7 @@ static zend_type zend_compile_typename( if (ast->kind == ZEND_AST_TYPE_UNION) { zend_ast_list *list = zend_ast_get_list(ast); zend_type_list *type_list; + bool is_composite = false; ALLOCA_FLAG(use_heap) type_list = do_alloca(ZEND_TYPE_LIST_SIZE(list->children), use_heap); @@ -6218,7 +6342,37 @@ static zend_type zend_compile_typename( for (uint32_t i = 0; i < list->children; i++) { zend_ast *type_ast = list->child[i]; - zend_type single_type = zend_compile_single_typename(type_ast); + zend_type single_type; + + if (type_ast->kind == ZEND_AST_TYPE_INTERSECTION) { + is_composite = true; + /* The first class type can be stored directly as the type ptr payload. */ + if (ZEND_TYPE_IS_COMPLEX(type) && !ZEND_TYPE_HAS_LIST(type)) { + /* Switch from single name to name list. */ + type_list->num_types = 1; + type_list->types[0] = type; + ZEND_TYPE_FULL_MASK(type_list->types[0]) &= ~_ZEND_TYPE_MAY_BE_MASK; + ZEND_TYPE_SET_LIST(type, type_list); + } + + single_type = zend_compile_typename(type_ast, false); + ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(single_type)); + + type_list->types[type_list->num_types++] = single_type; + + /* Check for trivially redundant class types */ + for (size_t i = 0; i < type_list->num_types - 1; i++) { + if (ZEND_TYPE_IS_INTERSECTION(type_list->types[i])) { + zend_are_intersection_types_redundant(single_type, type_list->types[i]); + continue; + } + /* Type from type list is a simple type */ + zend_is_intersection_type_redundant_by_single_type(single_type, type_list->types[i]); + } + continue; + } + + single_type = zend_compile_single_typename(type_ast); uint32_t single_type_mask = ZEND_TYPE_PURE_MASK(single_type); if (single_type_mask == MAY_BE_ANY) { @@ -6241,7 +6395,7 @@ static zend_type zend_compile_typename( ZEND_TYPE_FULL_MASK(single_type) &= ~_ZEND_TYPE_MAY_BE_MASK; if (ZEND_TYPE_IS_COMPLEX(single_type)) { - if (!ZEND_TYPE_IS_COMPLEX(type)) { + if (!ZEND_TYPE_IS_COMPLEX(type) && !is_composite) { /* The first class type can be stored directly as the type ptr payload. */ ZEND_TYPE_SET_PTR(type, ZEND_TYPE_NAME(single_type)); ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_NAME_BIT; @@ -6257,14 +6411,7 @@ static zend_type zend_compile_typename( type_list->types[type_list->num_types++] = single_type; /* Check for trivially redundant class types */ - for (size_t i = 0; i < type_list->num_types - 1; i++) { - if (zend_string_equals_ci( - ZEND_TYPE_NAME(type_list->types[i]), ZEND_TYPE_NAME(single_type))) { - zend_string *single_type_str = zend_type_to_string(single_type); - zend_error_noreturn(E_COMPILE_ERROR, - "Duplicate type %s is redundant", ZSTR_VAL(single_type_str)); - } - } + zend_is_type_list_redundant_by_single_type(type_list, single_type); } } } @@ -6321,14 +6468,7 @@ static zend_type zend_compile_typename( type_list->types[type_list->num_types++] = single_type; /* Check for trivially redundant class types */ - for (size_t i = 0; i < type_list->num_types - 1; i++) { - if (zend_string_equals_ci( - ZEND_TYPE_NAME(type_list->types[i]), ZEND_TYPE_NAME(single_type))) { - zend_string *single_type_str = zend_type_to_string(single_type); - zend_error_noreturn(E_COMPILE_ERROR, - "Duplicate type %s is redundant", ZSTR_VAL(single_type_str)); - } - } + zend_is_type_list_redundant_by_single_type(type_list, single_type); } ZEND_ASSERT(list->children == type_list->num_types); @@ -6642,12 +6782,12 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 } if (force_nullable && ZEND_TYPE_IS_INTERSECTION(arg_info->type)) { + /* We drop the nullable type flag to generate the correct type string */ + ZEND_TYPE_FULL_MASK(arg_info->type) = ZEND_TYPE_FULL_MASK(arg_info->type) & ~MAY_BE_NULL; zend_string *type_str = zend_type_to_string(arg_info->type); zend_error_noreturn(E_COMPILE_ERROR, "Cannot use null as default value for parameter $%s of type %s", - /* We move type_str pointer one char forward to skip the '?' generated by - * the call to zend_compile_typename() */ - ZSTR_VAL(name), ZSTR_VAL(type_str)+1); + ZSTR_VAL(name), ZSTR_VAL(type_str)); } if (default_type != IS_UNDEF && default_type != IS_CONSTANT_AST && !force_nullable @@ -7210,6 +7350,19 @@ static void zend_compile_func_decl(znode *result, zend_ast *ast, bool toplevel) } else if (uses_ast) { zend_compile_closure_uses(uses_ast); } + + if (ast->kind == ZEND_AST_ARROW_FUNC) { + bool needs_return = true; + if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + zend_arg_info *return_info = CG(active_op_array)->arg_info - 1; + needs_return = !ZEND_TYPE_CONTAINS_CODE(return_info->type, IS_NEVER); + } + if (needs_return) { + stmt_ast = zend_ast_create(ZEND_AST_RETURN, stmt_ast); + decl->child[2] = stmt_ast; + } + } + zend_compile_stmt(stmt_ast); if (is_method) { @@ -9612,7 +9765,8 @@ static bool zend_is_allowed_in_const_expr(zend_ast_kind kind) /* {{{ */ || kind == ZEND_AST_MAGIC_CONST || kind == ZEND_AST_COALESCE || kind == ZEND_AST_CONST_ENUM_INIT || kind == ZEND_AST_NEW || kind == ZEND_AST_ARG_LIST - || kind == ZEND_AST_NAMED_ARG; + || kind == ZEND_AST_NAMED_ARG + || kind == ZEND_AST_PROP || kind == ZEND_AST_NULLSAFE_PROP; } /* }}} */ @@ -10473,6 +10627,13 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ case ZEND_AST_NAMED_ARG: zend_eval_const_expr(&ast->child[1]); return; + case ZEND_AST_CONST_ENUM_INIT: + zend_eval_const_expr(&ast->child[2]); + return; + case ZEND_AST_PROP: + zend_eval_const_expr(&ast->child[0]); + zend_eval_const_expr(&ast->child[1]); + return; default: return; } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 89c1b1f6579b4..5bcb1a58ec4e2 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -448,6 +448,7 @@ struct _zend_op_array { uint32_t required_num_args; zend_arg_info *arg_info; HashTable *attributes; + ZEND_MAP_PTR_DEF(void **, run_time_cache); /* END of common elements */ int cache_size; /* number of run_time_cache_slots * sizeof(void*) */ @@ -456,7 +457,6 @@ struct _zend_op_array { uint32_t last; /* number of opcodes */ zend_op *opcodes; - ZEND_MAP_PTR_DEF(void **, run_time_cache); ZEND_MAP_PTR_DEF(HashTable *, static_variables_ptr); HashTable *static_variables; zend_string **vars; /* names of CV variables */ @@ -503,6 +503,7 @@ typedef struct _zend_internal_function { uint32_t required_num_args; zend_internal_arg_info *arg_info; HashTable *attributes; + ZEND_MAP_PTR_DEF(void **, run_time_cache); /* END of common elements */ zif_handler handler; @@ -527,6 +528,7 @@ union _zend_function { uint32_t required_num_args; zend_arg_info *arg_info; /* index -1 represents the return value info, if any */ HashTable *attributes; + ZEND_MAP_PTR_DEF(void **, run_time_cache); } common; zend_op_array op_array; diff --git a/Zend/zend_constants.stub.php b/Zend/zend_constants.stub.php index 191fbd2618778..289f6fb0531d5 100644 --- a/Zend/zend_constants.stub.php +++ b/Zend/zend_constants.stub.php @@ -4,96 +4,96 @@ /** * @var int - * @cname E_ERROR + * @cvalue E_ERROR */ const E_ERROR = UNKNOWN; /** * @var int - * @cname E_WARNING + * @cvalue E_WARNING */ const E_WARNING = UNKNOWN; /** * @var int - * @cname E_PARSE + * @cvalue E_PARSE */ const E_PARSE = UNKNOWN; /** * @var int - * @cname E_NOTICE + * @cvalue E_NOTICE */ const E_NOTICE = UNKNOWN; /** * @var int - * @cname E_CORE_ERROR + * @cvalue E_CORE_ERROR */ const E_CORE_ERROR = UNKNOWN; /** * @var int - * @cname E_CORE_WARNING + * @cvalue E_CORE_WARNING */ const E_CORE_WARNING = UNKNOWN; /** * @var int - * @cname E_COMPILE_ERROR + * @cvalue E_COMPILE_ERROR */ const E_COMPILE_ERROR = UNKNOWN; /** * @var int - * @cname E_COMPILE_WARNING + * @cvalue E_COMPILE_WARNING */ const E_COMPILE_WARNING = UNKNOWN; /** * @var int - * @cname E_USER_ERROR + * @cvalue E_USER_ERROR */ const E_USER_ERROR = UNKNOWN; /** * @var int - * @cname E_USER_WARNING + * @cvalue E_USER_WARNING */ const E_USER_WARNING = UNKNOWN; /** * @var int - * @cname E_USER_NOTICE + * @cvalue E_USER_NOTICE */ const E_USER_NOTICE = UNKNOWN; /** * @var int - * @cname E_STRICT + * @cvalue E_STRICT */ const E_STRICT = UNKNOWN; /** * @var int - * @cname E_RECOVERABLE_ERROR + * @cvalue E_RECOVERABLE_ERROR */ const E_RECOVERABLE_ERROR = UNKNOWN; /** * @var int - * @cname E_DEPRECATED + * @cvalue E_DEPRECATED */ const E_DEPRECATED = UNKNOWN; /** * @var int - * @cname E_USER_DEPRECATED + * @cvalue E_USER_DEPRECATED */ const E_USER_DEPRECATED = UNKNOWN; /** * @var int - * @cname E_ALL + * @cvalue E_ALL */ const E_ALL = UNKNOWN; diff --git a/Zend/zend_constants_arginfo.h b/Zend/zend_constants_arginfo.h index d51ac27af13b1..0665c0b942539 100644 --- a/Zend/zend_constants_arginfo.h +++ b/Zend/zend_constants_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: f417ea0f3a43036f0abc87856c83f4c93395405a */ + * Stub hash: 50b960193f55c7b09316355a0c0ae1d572ca9694 */ diff --git a/Zend/zend_enum.c b/Zend/zend_enum.c index a4a450d22fba6..288e019c91383 100644 --- a/Zend/zend_enum.c +++ b/Zend/zend_enum.c @@ -22,6 +22,7 @@ #include "zend_enum_arginfo.h" #include "zend_interfaces.h" #include "zend_enum.h" +#include "zend_extensions.h" #define ZEND_ENUM_DISALLOW_MAGIC_METHOD(propertyName, methodName) \ do { \ @@ -192,14 +193,15 @@ zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce) uint32_t backing_type = ce->enum_backing_type; ZEND_ASSERT(backing_type != IS_UNDEF); - ce->backed_enum_table = emalloc(sizeof(HashTable)); - zend_hash_init(ce->backed_enum_table, 0, NULL, ZVAL_PTR_DTOR, 0); + HashTable *backed_enum_table = emalloc(sizeof(HashTable)); + zend_hash_init(backed_enum_table, 0, NULL, ZVAL_PTR_DTOR, 0); + zend_class_set_backed_enum_table(ce, backed_enum_table); zend_string *enum_class_name = ce->name; zend_string *name; zval *val; - ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(&ce->constants_table, name, val) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(CE_CONSTANTS_TABLE(ce), name, val) { zend_class_constant *c = Z_PTR_P(val); if ((ZEND_CLASS_CONST_FLAGS(c) & ZEND_CLASS_CONST_IS_CASE) == 0) { continue; @@ -218,7 +220,7 @@ zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce) if (ce->enum_backing_type == IS_LONG) { zend_long long_key = Z_LVAL_P(case_value); - zval *existing_case_name = zend_hash_index_find(ce->backed_enum_table, long_key); + zval *existing_case_name = zend_hash_index_find(backed_enum_table, long_key); if (existing_case_name) { zend_throw_error(NULL, "Duplicate value in enum %s for cases %s and %s", ZSTR_VAL(enum_class_name), @@ -226,11 +228,11 @@ zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce) ZSTR_VAL(name)); goto failure; } - zend_hash_index_add_new(ce->backed_enum_table, long_key, case_name); + zend_hash_index_add_new(backed_enum_table, long_key, case_name); } else { ZEND_ASSERT(ce->enum_backing_type == IS_STRING); zend_string *string_key = Z_STR_P(case_value); - zval *existing_case_name = zend_hash_find(ce->backed_enum_table, string_key); + zval *existing_case_name = zend_hash_find(backed_enum_table, string_key); if (existing_case_name != NULL) { zend_throw_error(NULL, "Duplicate value in enum %s for cases %s and %s", ZSTR_VAL(enum_class_name), @@ -238,15 +240,15 @@ zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce) ZSTR_VAL(name)); goto failure; } - zend_hash_add_new(ce->backed_enum_table, string_key, case_name); + zend_hash_add_new(backed_enum_table, string_key, case_name); } } ZEND_HASH_FOREACH_END(); return SUCCESS; failure: - zend_hash_release(ce->backed_enum_table); - ce->backed_enum_table = NULL; + zend_hash_release(backed_enum_table); + zend_class_set_backed_enum_table(ce, NULL); return FAILURE; } @@ -282,16 +284,22 @@ ZEND_API zend_result zend_enum_get_case_by_value(zend_object **result, zend_clas } } + HashTable *backed_enum_table = CE_BACKED_ENUM_TABLE(ce); + if (!backed_enum_table) { + goto not_found; + } + zval *case_name_zv; if (ce->enum_backing_type == IS_LONG) { - case_name_zv = zend_hash_index_find(ce->backed_enum_table, long_key); + case_name_zv = zend_hash_index_find(backed_enum_table, long_key); } else { ZEND_ASSERT(ce->enum_backing_type == IS_STRING); ZEND_ASSERT(string_key != NULL); - case_name_zv = zend_hash_find(ce->backed_enum_table, string_key); + case_name_zv = zend_hash_find(backed_enum_table, string_key); } if (case_name_zv == NULL) { +not_found: if (try) { *result = NULL; return SUCCESS; @@ -394,59 +402,48 @@ static ZEND_NAMED_FUNCTION(zend_enum_try_from_func) zend_enum_from_base(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } +static void zend_enum_register_func(zend_class_entry *ce, zend_known_string_id name_id, zend_internal_function *zif) { + zend_string *name = ZSTR_KNOWN(name_id); + zif->type = ZEND_INTERNAL_FUNCTION; + zif->module = EG(current_module); + zif->scope = ce; + ZEND_MAP_PTR_NEW(zif->run_time_cache); + ZEND_MAP_PTR_SET(zif->run_time_cache, zend_arena_alloc(&CG(arena), zend_internal_run_time_cache_reserved_size())); + + if (!zend_hash_add_ptr(&ce->function_table, name, zif)) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", ZSTR_VAL(ce->name), ZSTR_VAL(name)); + } +} + void zend_enum_register_funcs(zend_class_entry *ce) { const uint32_t fn_flags = ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_ARENA_ALLOCATED; - zend_internal_function *cases_function = - zend_arena_alloc(&CG(arena), sizeof(zend_internal_function)); - memset(cases_function, 0, sizeof(zend_internal_function)); - cases_function->type = ZEND_INTERNAL_FUNCTION; - cases_function->module = EG(current_module); + zend_internal_function *cases_function = zend_arena_calloc(&CG(arena), sizeof(zend_internal_function), 1); cases_function->handler = zend_enum_cases_func; cases_function->function_name = ZSTR_KNOWN(ZEND_STR_CASES); - cases_function->scope = ce; cases_function->fn_flags = fn_flags; cases_function->arg_info = (zend_internal_arg_info *) (arginfo_class_UnitEnum_cases + 1); - if (!zend_hash_add_ptr(&ce->function_table, ZSTR_KNOWN(ZEND_STR_CASES), cases_function)) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::cases()", ZSTR_VAL(ce->name)); - } + zend_enum_register_func(ce, ZEND_STR_CASES, cases_function); if (ce->enum_backing_type != IS_UNDEF) { - zend_internal_function *from_function = - zend_arena_alloc(&CG(arena), sizeof(zend_internal_function)); - memset(from_function, 0, sizeof(zend_internal_function)); - from_function->type = ZEND_INTERNAL_FUNCTION; - from_function->module = EG(current_module); + zend_internal_function *from_function = zend_arena_calloc(&CG(arena), sizeof(zend_internal_function), 1); from_function->handler = zend_enum_from_func; from_function->function_name = ZSTR_KNOWN(ZEND_STR_FROM); - from_function->scope = ce; from_function->fn_flags = fn_flags; from_function->num_args = 1; from_function->required_num_args = 1; from_function->arg_info = (zend_internal_arg_info *) (arginfo_class_BackedEnum_from + 1); - if (!zend_hash_add_ptr(&ce->function_table, ZSTR_KNOWN(ZEND_STR_FROM), from_function)) { - zend_error_noreturn(E_COMPILE_ERROR, - "Cannot redeclare %s::from()", ZSTR_VAL(ce->name)); - } + zend_enum_register_func(ce, ZEND_STR_FROM, from_function); - zend_internal_function *try_from_function = - zend_arena_alloc(&CG(arena), sizeof(zend_internal_function)); - memset(try_from_function, 0, sizeof(zend_internal_function)); - try_from_function->type = ZEND_INTERNAL_FUNCTION; - try_from_function->module = EG(current_module); + zend_internal_function *try_from_function = zend_arena_calloc(&CG(arena), sizeof(zend_internal_function), 1); try_from_function->handler = zend_enum_try_from_func; try_from_function->function_name = ZSTR_KNOWN(ZEND_STR_TRYFROM); - try_from_function->scope = ce; try_from_function->fn_flags = fn_flags; try_from_function->num_args = 1; try_from_function->required_num_args = 1; try_from_function->arg_info = (zend_internal_arg_info *) (arginfo_class_BackedEnum_tryFrom + 1); - if (!zend_hash_add_ptr( - &ce->function_table, ZSTR_KNOWN(ZEND_STR_TRYFROM_LOWERCASE), try_from_function)) { - zend_error_noreturn(E_COMPILE_ERROR, - "Cannot redeclare %s::tryFrom()", ZSTR_VAL(ce->name)); - } + zend_enum_register_func(ce, ZEND_STR_TRYFROM_LOWERCASE, try_from_function); } } @@ -491,8 +488,9 @@ ZEND_API zend_class_entry *zend_register_internal_enum( ce->ce_flags |= ZEND_ACC_ENUM; ce->enum_backing_type = type; if (type != IS_UNDEF) { - ce->backed_enum_table = pemalloc(sizeof(HashTable), 1); - zend_hash_init(ce->backed_enum_table, 0, NULL, ZVAL_PTR_DTOR, 1); + HashTable *backed_enum_table = pemalloc(sizeof(HashTable), 1); + zend_hash_init(backed_enum_table, 0, NULL, ZVAL_PTR_DTOR, 1); + zend_class_set_backed_enum_table(ce, backed_enum_table); } zend_enum_register_props(ce); @@ -557,12 +555,14 @@ ZEND_API void zend_enum_add_case(zend_class_entry *ce, zend_string *case_name, z zval_make_interned_string(value); } + HashTable *backed_enum_table = CE_BACKED_ENUM_TABLE(ce); + zval case_name_zv; ZVAL_STR(&case_name_zv, case_name); if (Z_TYPE_P(value) == IS_LONG) { - zend_hash_index_add_new(ce->backed_enum_table, Z_LVAL_P(value), &case_name_zv); + zend_hash_index_add_new(backed_enum_table, Z_LVAL_P(value), &case_name_zv); } else { - zend_hash_add_new(ce->backed_enum_table, Z_STR_P(value), &case_name_zv); + zend_hash_add_new(backed_enum_table, Z_STR_P(value), &case_name_zv); } } else { ZEND_ASSERT(ce->enum_backing_type == IS_UNDEF); diff --git a/Zend/zend_exceptions.stub.php b/Zend/zend_exceptions.stub.php index 2deab70209278..84109b021a746 100644 --- a/Zend/zend_exceptions.stub.php +++ b/Zend/zend_exceptions.stub.php @@ -2,6 +2,8 @@ /** @generate-class-entries */ +require "zend_constants.stub.php"; + interface Throwable extends Stringable { public function getMessage(): string; diff --git a/Zend/zend_exceptions_arginfo.h b/Zend/zend_exceptions_arginfo.h index 0ab8068149679..58538905a6a89 100644 --- a/Zend/zend_exceptions_arginfo.h +++ b/Zend/zend_exceptions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: bee3fd13c5d5a6d09e217452998389d1b595157a */ + * Stub hash: 4cf2c620393f468968a219b5bd12a2b5f6b03ecc */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Throwable_getMessage, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index c8888a4baf6f5..45cf790bfa818 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -144,6 +144,7 @@ ZEND_API const zend_internal_function zend_pass_function = { 0, /* required_num_args */ (zend_internal_arg_info *) zend_pass_function_arg_info + 1, /* arg_info */ NULL, /* attributes */ + NULL, /* run_time_cache */ ZEND_FN(pass), /* handler */ NULL, /* module */ {NULL,NULL,NULL,NULL} /* reserved */ @@ -853,6 +854,12 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_modification_error( ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name)); } +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_indirect_modification_error(zend_property_info *info) +{ + zend_throw_error(NULL, "Cannot indirectly modify readonly property %s::$%s", + ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name)); +} + static zend_class_entry *resolve_single_class_type(zend_string *name, zend_class_entry *self_ce) { if (zend_string_equals_literal_ci(name, "self")) { return self_ce; @@ -877,20 +884,38 @@ static zend_always_inline zend_class_entry *zend_ce_from_type( return resolve_single_class_type(name, info->ce); } +static bool zend_check_intersection_for_property_class_type(zend_type_list *intersection_type_list, + zend_property_info *info, zend_class_entry *object_ce) +{ + zend_type *list_type; + + ZEND_TYPE_LIST_FOREACH(intersection_type_list, list_type) { + ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type)); + zend_class_entry *ce = zend_ce_from_type(info, list_type); + if (!ce || !instanceof_function(object_ce, ce)) { + return false; + } + } ZEND_TYPE_LIST_FOREACH_END(); + return true; +} + static bool zend_check_and_resolve_property_class_type( zend_property_info *info, zend_class_entry *object_ce) { if (ZEND_TYPE_HAS_LIST(info->type)) { zend_type *list_type; if (ZEND_TYPE_IS_INTERSECTION(info->type)) { - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(info->type), list_type) { - zend_class_entry *ce = zend_ce_from_type(info, list_type); - if (!ce || !instanceof_function(object_ce, ce)) { - return false; - } - } ZEND_TYPE_LIST_FOREACH_END(); - return true; + return zend_check_intersection_for_property_class_type( + ZEND_TYPE_LIST(info->type), info, object_ce); } else { ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(info->type), list_type) { + if (ZEND_TYPE_IS_INTERSECTION(*list_type)) { + if (zend_check_intersection_for_property_class_type( + ZEND_TYPE_LIST(*list_type), info, object_ce)) { + return true; + } + continue; + } + ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type)); zend_class_entry *ce = zend_ce_from_type(info, list_type); if (ce && instanceof_function(object_ce, ce)) { return true; @@ -1006,6 +1031,22 @@ static zend_always_inline zend_class_entry *zend_fetch_ce_from_cache_slot( return ce; } +static bool zend_check_intersection_type_from_cache_slot(zend_type_list *intersection_type_list, + zend_class_entry *arg_ce, void **cache_slot) +{ + zend_class_entry *ce; + zend_type *list_type; + ZEND_TYPE_LIST_FOREACH(intersection_type_list, list_type) { + ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type); + /* If type is not an instance of one of the types taking part in the + * intersection it cannot be a valid instance of the whole intersection type. */ + if (!ce || !instanceof_function(arg_ce, ce)) { + return false; + } + } ZEND_TYPE_LIST_FOREACH_END(); + return true; +} + static zend_always_inline bool zend_check_type_slow( zend_type *type, zval *arg, zend_reference *ref, void **cache_slot, bool is_return_type, bool is_internal) @@ -1030,11 +1071,19 @@ static zend_always_inline bool zend_check_type_slow( return true; } else { ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), list_type) { - ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type); - /* Instance of a single type part of a union is sufficient to pass the type check */ - if (ce && instanceof_function(Z_OBJCE_P(arg), ce)) { - return true; + if (ZEND_TYPE_IS_INTERSECTION(*list_type)) { + if (zend_check_intersection_type_from_cache_slot(ZEND_TYPE_LIST(*list_type), Z_OBJCE_P(arg), cache_slot)) { + return true; + } + } else { + ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type)); + ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type); + /* Instance of a single type part of a union is sufficient to pass the type check */ + if (ce && instanceof_function(Z_OBJCE_P(arg), ce)) { + return true; + } } + if (HAVE_CACHE_SLOT) { cache_slot++; } @@ -1051,7 +1100,8 @@ static zend_always_inline bool zend_check_type_slow( } type_mask = ZEND_TYPE_FULL_MASK(*type); - if ((type_mask & MAY_BE_CALLABLE) && zend_is_callable(arg, 0, NULL)) { + if ((type_mask & MAY_BE_CALLABLE) && + zend_is_callable(arg, is_internal ? IS_CALLABLE_SUPPRESS_DEPRECATIONS : 0, NULL)) { return 1; } if ((type_mask & MAY_BE_STATIC) && zend_value_instanceof_static(arg)) { @@ -1574,14 +1624,6 @@ ZEND_API ZEND_COLD void zend_wrong_string_offset_error(void) zend_throw_error(NULL, "%s", msg); } -static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_wrong_property_read(zval *object, zval *property) -{ - zend_string *tmp_property_name; - zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name); - zend_error(E_WARNING, "Attempt to read property \"%s\" on %s", ZSTR_VAL(property_name), zend_zval_type_name(object)); - zend_tmp_string_release(tmp_property_name); -} - ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(const zend_function *fbc) { if (fbc->common.scope) { diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 36cf921f1a5cd..b43f038e4928c 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -74,6 +74,7 @@ ZEND_API ZEND_COLD zval* ZEND_FASTCALL zend_undefined_index_write(HashTable *ht, ZEND_API ZEND_COLD void zend_wrong_string_offset_error(void); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_modification_error(zend_property_info *info); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_indirect_modification_error(zend_property_info *info); ZEND_API bool zend_verify_scalar_type_hint(uint32_t type_mask, zval *arg, bool strict, bool is_internal_arg); ZEND_API ZEND_COLD void zend_verify_arg_error( @@ -348,9 +349,9 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_cannot_pass_by_reference(uint32_t arg ZEND_API void zend_set_timeout(zend_long seconds, bool reset_signals); ZEND_API void zend_unset_timeout(void); ZEND_API ZEND_NORETURN void ZEND_FASTCALL zend_timeout(void); -ZEND_API zend_class_entry *zend_fetch_class(zend_string *class_name, int fetch_type); -ZEND_API zend_class_entry *zend_fetch_class_with_scope(zend_string *class_name, int fetch_type, zend_class_entry *scope); -ZEND_API zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, zend_string *lcname, int fetch_type); +ZEND_API zend_class_entry *zend_fetch_class(zend_string *class_name, uint32_t fetch_type); +ZEND_API zend_class_entry *zend_fetch_class_with_scope(zend_string *class_name, uint32_t fetch_type, zend_class_entry *scope); +ZEND_API zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, zend_string *lcname, uint32_t fetch_type); ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function(zend_string *name); ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function_str(const char *name, size_t len); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index e203556a8ecd7..a46959373ad7d 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -346,6 +346,12 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown) } } + if (ce->type == ZEND_USER_CLASS && ce->backed_enum_table) { + ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_IMMUTABLE)); + zend_hash_release(ce->backed_enum_table); + ce->backed_enum_table = NULL; + } + if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) { zend_op_array *op_array; ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { @@ -929,6 +935,7 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_ #if ZEND_DEBUG bool should_throw = zend_internal_call_should_throw(func, call); #endif + ZEND_OBSERVER_FCALL_BEGIN(call); if (EXPECTED(zend_execute_internal == NULL)) { /* saves one function call if zend_execute_internal is not used */ func->internal_function.handler(call, fci->retval); @@ -947,6 +954,7 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_ ? Z_ISREF_P(fci->retval) : !Z_ISREF_P(fci->retval)); } #endif + ZEND_OBSERVER_FCALL_END(call, fci->retval); EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { @@ -1044,7 +1052,7 @@ ZEND_API zend_result zend_call_method_if_exists( fci.named_params = NULL; zend_fcall_info_cache fcc; - if (!zend_is_callable_ex(&fci.function_name, fci.object, 0, NULL, &fcc, NULL)) { + if (!zend_is_callable_ex(&fci.function_name, fci.object, IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, &fcc, NULL)) { ZVAL_UNDEF(retval); return FAILURE; } @@ -1528,7 +1536,7 @@ void zend_unset_timeout(void) /* {{{ */ } /* }}} */ -static ZEND_COLD void report_class_fetch_error(zend_string *class_name, int fetch_type) +static ZEND_COLD void report_class_fetch_error(zend_string *class_name, uint32_t fetch_type) { if (fetch_type & ZEND_FETCH_CLASS_SILENT) { return; @@ -1550,10 +1558,10 @@ static ZEND_COLD void report_class_fetch_error(zend_string *class_name, int fetc } } -zend_class_entry *zend_fetch_class(zend_string *class_name, int fetch_type) /* {{{ */ +zend_class_entry *zend_fetch_class(zend_string *class_name, uint32_t fetch_type) /* {{{ */ { zend_class_entry *ce, *scope; - int fetch_sub_type = fetch_type & ZEND_FETCH_CLASS_MASK; + uint32_t fetch_sub_type = fetch_type & ZEND_FETCH_CLASS_MASK; check_fetch_type: switch (fetch_sub_type) { @@ -1599,7 +1607,7 @@ zend_class_entry *zend_fetch_class(zend_string *class_name, int fetch_type) /* { /* }}} */ zend_class_entry *zend_fetch_class_with_scope( - zend_string *class_name, int fetch_type, zend_class_entry *scope) + zend_string *class_name, uint32_t fetch_type, zend_class_entry *scope) { zend_class_entry *ce; switch (fetch_type & ZEND_FETCH_CLASS_MASK) { @@ -1631,7 +1639,7 @@ zend_class_entry *zend_fetch_class_with_scope( return ce; } -zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, zend_string *key, int fetch_type) /* {{{ */ +zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, zend_string *key, uint32_t fetch_type) /* {{{ */ { zend_class_entry *ce = zend_lookup_class_ex(class_name, key, fetch_type); if (!ce) { diff --git a/Zend/zend_extensions.c b/Zend/zend_extensions.c index cbad169732e41..1f3687642ab67 100644 --- a/Zend/zend_extensions.c +++ b/Zend/zend_extensions.c @@ -280,6 +280,40 @@ ZEND_API int zend_get_op_array_extension_handles(const char *module_name, int ha return handle; } +ZEND_API size_t zend_internal_run_time_cache_reserved_size() { + return zend_op_array_extension_handles * sizeof(void *); +} + +ZEND_API void zend_init_internal_run_time_cache() { + size_t rt_size = zend_internal_run_time_cache_reserved_size(); + if (rt_size) { + size_t functions = zend_hash_num_elements(CG(function_table)); + zend_class_entry *ce; + ZEND_HASH_MAP_FOREACH_PTR(CG(class_table), ce) { + functions += zend_hash_num_elements(&ce->function_table); + } ZEND_HASH_FOREACH_END(); + + char *ptr = zend_arena_calloc(&CG(arena), functions, rt_size); + zend_internal_function *zif; + ZEND_HASH_MAP_FOREACH_PTR(CG(function_table), zif) { + if (!ZEND_USER_CODE(zif->type) && ZEND_MAP_PTR_GET(zif->run_time_cache) == NULL) + { + ZEND_MAP_PTR_SET(zif->run_time_cache, (void *)ptr); + ptr += rt_size; + } + } ZEND_HASH_FOREACH_END(); + ZEND_HASH_MAP_FOREACH_PTR(CG(class_table), ce) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, zif) { + if (!ZEND_USER_CODE(zif->type) && ZEND_MAP_PTR_GET(zif->run_time_cache) == NULL) + { + ZEND_MAP_PTR_SET(zif->run_time_cache, (void *)ptr); + ptr += rt_size; + } + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); + } +} + ZEND_API zend_extension *zend_get_extension(const char *extension_name) { zend_llist_element *element; diff --git a/Zend/zend_extensions.h b/Zend/zend_extensions.h index 95eb8dd10ef67..c32ed5de1adad 100644 --- a/Zend/zend_extensions.h +++ b/Zend/zend_extensions.h @@ -145,6 +145,9 @@ void zend_startup_extensions_mechanism(void); void zend_startup_extensions(void); void zend_shutdown_extensions(void); +ZEND_API size_t zend_internal_run_time_cache_reserved_size(void); +ZEND_API void zend_init_internal_run_time_cache(void); + BEGIN_EXTERN_C() ZEND_API zend_result zend_load_extension(const char *path); ZEND_API zend_result zend_load_extension_handle(DL_HANDLE handle, const char *path); diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 1fec85528fbb3..80a70d87f6f28 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -24,6 +24,7 @@ #include "zend_exceptions.h" #include "zend_builtin_functions.h" #include "zend_observer.h" +#include "zend_mmap.h" #include "zend_fibers.h" #include "zend_fibers_arginfo.h" @@ -211,6 +212,8 @@ static zend_fiber_stack *zend_fiber_stack_allocate(size_t size) return NULL; } + zend_mmap_set_name(pointer, alloc_size, "zend_fiber_stack"); + # if ZEND_FIBER_GUARD_PAGES if (mprotect(pointer, ZEND_FIBER_GUARD_PAGES * page_size, PROT_NONE) < 0) { zend_throw_exception_ex(NULL, 0, "Fiber stack protect failed: mprotect failed: %s (%d)", strerror(errno), errno); @@ -644,12 +647,23 @@ static HashTable *zend_fiber_object_gc(zend_object *object, zval **table, int *n ZEND_METHOD(Fiber, __construct) { - zend_fiber *fiber = (zend_fiber *) Z_OBJ_P(ZEND_THIS); + zend_fcall_info fci; + zend_fcall_info_cache fcc; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_FUNC(fiber->fci, fiber->fci_cache) + Z_PARAM_FUNC(fci, fcc) ZEND_PARSE_PARAMETERS_END(); + zend_fiber *fiber = (zend_fiber *) Z_OBJ_P(ZEND_THIS); + + if (UNEXPECTED(fiber->context.status != ZEND_FIBER_STATUS_INIT || Z_TYPE(fiber->fci.function_name) != IS_UNDEF)) { + zend_throw_error(zend_ce_fiber_error, "Cannot call constructor twice"); + RETURN_THROWS(); + } + + fiber->fci = fci; + fiber->fci_cache = fcc; + // Keep a reference to closures or callable objects while the fiber is running. Z_TRY_ADDREF(fiber->fci.function_name); } diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index fe4af53ecbdcc..ffdb0e0385cd4 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -2396,6 +2396,26 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source) return target; } +ZEND_API HashTable* zend_array_to_list(HashTable *source) +{ + HashTable *result = _zend_new_array(zend_hash_num_elements(source)); + zend_hash_real_init_packed(result); + + ZEND_HASH_FILL_PACKED(result) { + zval *entry; + + ZEND_HASH_FOREACH_VAL(source, entry) { + if (UNEXPECTED(Z_ISREF_P(entry) && Z_REFCOUNT_P(entry) == 1)) { + entry = Z_REFVAL_P(entry); + } + Z_TRY_ADDREF_P(entry); + ZEND_HASH_FILL_ADD(entry); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FILL_END(); + + return result; +} + ZEND_API void ZEND_FASTCALL zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, bool overwrite) { diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 02244380da10f..76898087e27ac 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -320,6 +320,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_new_pair(zval *val1, zval *val2); ZEND_API uint32_t zend_array_count(HashTable *ht); ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source); ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht); +ZEND_API HashTable* zend_array_to_list(HashTable *source); ZEND_API void ZEND_FASTCALL zend_symtable_clean(HashTable *ht); ZEND_API HashTable* ZEND_FASTCALL zend_symtable_to_proptable(HashTable *ht); ZEND_API HashTable* ZEND_FASTCALL zend_proptable_to_symtable(HashTable *ht, bool always_duplicate); @@ -1555,8 +1556,8 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht, /* Check if an array is a list */ static zend_always_inline bool zend_array_is_list(zend_array *array) { - zend_long expected_idx = 0; - zend_long num_idx; + zend_ulong expected_idx = 0; + zend_ulong num_idx; zend_string* str_idx; /* Empty arrays are lists */ if (zend_hash_num_elements(array) == 0) { diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 1b0d57b2e7cae..b0008e889b5ac 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -354,10 +354,9 @@ static void track_class_dependency(zend_class_entry *ce, zend_string *class_name { HashTable *ht; + ZEND_ASSERT(class_name); if (!CG(current_linking_class) || ce == CG(current_linking_class)) { return; - } else if (!class_name) { - class_name = ce->name; } else if (zend_string_equals_literal_ci(class_name, "self") || zend_string_equals_literal_ci(class_name, "parent")) { return; @@ -465,6 +464,28 @@ static inheritance_status zend_is_class_subtype_of_type( * class is the subtype of at least one of them (union) or all of them (intersection). */ bool is_intersection = ZEND_TYPE_IS_INTERSECTION(proto_type); ZEND_TYPE_FOREACH(proto_type, single_type) { + if (ZEND_TYPE_IS_INTERSECTION(*single_type)) { + inheritance_status subtype_status = zend_is_class_subtype_of_type( + fe_scope, fe_class_name, proto_scope, *single_type); + + switch (subtype_status) { + case INHERITANCE_ERROR: + if (is_intersection) { + return INHERITANCE_ERROR; + } + continue; + case INHERITANCE_UNRESOLVED: + have_unresolved = 1; + continue; + case INHERITANCE_SUCCESS: + if (!is_intersection) { + return INHERITANCE_SUCCESS; + } + continue; + EMPTY_SWITCH_DEFAULT_CASE(); + } + } + zend_class_entry *proto_ce; zend_string *proto_class_name = NULL; if (ZEND_TYPE_HAS_NAME(*single_type)) { @@ -518,6 +539,10 @@ static zend_string *get_class_from_type(zend_class_entry *scope, zend_type singl static void register_unresolved_classes(zend_class_entry *scope, zend_type type) { zend_type *single_type; ZEND_TYPE_FOREACH(type, single_type) { + if (ZEND_TYPE_HAS_LIST(*single_type)) { + register_unresolved_classes(scope, *single_type); + continue; + } if (ZEND_TYPE_HAS_NAME(*single_type)) { zend_string *class_name = resolve_class_name(scope, ZEND_TYPE_NAME(*single_type)); lookup_class_ex(scope, class_name, /* register_unresolved */ true); @@ -525,6 +550,72 @@ static void register_unresolved_classes(zend_class_entry *scope, zend_type type) } ZEND_TYPE_FOREACH_END(); } +static inheritance_status zend_is_intersection_subtype_of_type( + zend_class_entry *fe_scope, zend_type fe_type, + zend_class_entry *proto_scope, zend_type proto_type) +{ + bool have_unresolved = false; + zend_type *single_type; + uint32_t proto_type_mask = ZEND_TYPE_PURE_MASK(proto_type); + + /* Currently, for object type any class name would be allowed here. + * We still perform a class lookup for forward-compatibility reasons, + * as we may have named types in the future that are not classes + * (such as typedefs). */ + if (proto_type_mask & MAY_BE_OBJECT) { + ZEND_TYPE_FOREACH(fe_type, single_type) { + zend_string *fe_class_name = get_class_from_type(fe_scope, *single_type); + if (!fe_class_name) { + continue; + } + zend_class_entry *fe_ce = lookup_class(fe_scope, fe_class_name); + if (fe_ce) { + track_class_dependency(fe_ce, fe_class_name); + return INHERITANCE_SUCCESS; + } else { + have_unresolved = true; + } + } ZEND_TYPE_FOREACH_END(); + } + + /* U_1&...&U_n < V_1&...&V_m if forall V_j. exists U_i. U_i < V_j. + * U_1&...&U_n < V_1|...|V_m if exists V_j. exists U_i. U_i < V_j. + * As such, we need to iterate over proto_type (V_j) first and use a different + * quantifier depending on whether fe_type is a union or an intersection. */ + inheritance_status early_exit_status = + ZEND_TYPE_IS_INTERSECTION(proto_type) ? INHERITANCE_ERROR : INHERITANCE_SUCCESS; + ZEND_TYPE_FOREACH(proto_type, single_type) { + inheritance_status status; + + if (ZEND_TYPE_IS_INTERSECTION(*single_type)) { + status = zend_is_intersection_subtype_of_type( + fe_scope, fe_type, proto_scope, *single_type); + } else { + zend_string *proto_class_name = get_class_from_type(proto_scope, *single_type); + if (!proto_class_name) { + continue; + } + + zend_class_entry *proto_ce = NULL; + status = zend_is_intersection_subtype_of_class( + fe_scope, fe_type, proto_scope, proto_class_name, proto_ce); + } + + if (status == early_exit_status) { + return status; + } + if (status == INHERITANCE_UNRESOLVED) { + have_unresolved = true; + } + } ZEND_TYPE_FOREACH_END(); + + if (have_unresolved) { + return INHERITANCE_UNRESOLVED; + } + + return early_exit_status == INHERITANCE_ERROR ? INHERITANCE_SUCCESS : INHERITANCE_ERROR; +} + static inheritance_status zend_perform_covariant_type_check( zend_class_entry *fe_scope, zend_type fe_type, zend_class_entry *proto_scope, zend_type proto_type) @@ -565,48 +656,17 @@ static inheritance_status zend_perform_covariant_type_check( bool have_unresolved = false; if (ZEND_TYPE_IS_INTERSECTION(fe_type)) { - /* Currently, for object type any class name would be allowed here. - * We still perform a class lookup for forward-compatibility reasons, - * as we may have named types in the future that are not classes - * (such as typedefs). */ - if (proto_type_mask & MAY_BE_OBJECT) { - ZEND_TYPE_FOREACH(fe_type, single_type) { - zend_string *fe_class_name = get_class_from_type(fe_scope, *single_type); - if (!fe_class_name) { - continue; - } - zend_class_entry *fe_ce = lookup_class(fe_scope, fe_class_name); - if (fe_ce) { - track_class_dependency(fe_ce, fe_class_name); - return INHERITANCE_SUCCESS; - } else { - have_unresolved = true; - } - } ZEND_TYPE_FOREACH_END(); - } - - /* U_1&...&U_n < V_1&...&V_m if forall V_j. exists U_i. U_i < V_j. - * U_1&...&U_n < V_1|...|V_m if exists V_j. exists U_i. U_i < V_j. - * As such, we need to iterate over proto_type (V_j) first and use a different - * quantifier depending on whether fe_type is a union or an intersection. */ early_exit_status = ZEND_TYPE_IS_INTERSECTION(proto_type) ? INHERITANCE_ERROR : INHERITANCE_SUCCESS; - ZEND_TYPE_FOREACH(proto_type, single_type) { - zend_string *proto_class_name = get_class_from_type(proto_scope, *single_type); - if (!proto_class_name) { - continue; - } + inheritance_status status = zend_is_intersection_subtype_of_type( + fe_scope, fe_type, proto_scope, proto_type); - zend_class_entry *proto_ce = NULL; - inheritance_status status = zend_is_intersection_subtype_of_class( - fe_scope, fe_type, proto_scope, proto_class_name, proto_ce); - if (status == early_exit_status) { - return status; - } - if (status == INHERITANCE_UNRESOLVED) { - have_unresolved = true; - } - } ZEND_TYPE_FOREACH_END(); + if (status == early_exit_status) { + return status; + } + if (status == INHERITANCE_UNRESOLVED) { + have_unresolved = true; + } } else { /* U_1|...|U_n < V_1|...|V_m if forall U_i. exists V_j. U_i < V_j. * U_1|...|U_n < V_1&...&V_m if forall U_i. forall V_j. U_i < V_j. @@ -614,13 +674,21 @@ static inheritance_status zend_perform_covariant_type_check( * whether proto_type is a union or intersection (only the inner check differs). */ early_exit_status = INHERITANCE_ERROR; ZEND_TYPE_FOREACH(fe_type, single_type) { - zend_string *fe_class_name = get_class_from_type(fe_scope, *single_type); - if (!fe_class_name) { - continue; + inheritance_status status; + /* Union has an intersection type as it's member */ + if (ZEND_TYPE_IS_INTERSECTION(*single_type)) { + status = zend_is_intersection_subtype_of_type( + fe_scope, *single_type, proto_scope, proto_type); + } else { + zend_string *fe_class_name = get_class_from_type(fe_scope, *single_type); + if (!fe_class_name) { + continue; + } + + status = zend_is_class_subtype_of_type( + fe_scope, fe_class_name, proto_scope, proto_type); } - inheritance_status status = zend_is_class_subtype_of_type( - fe_scope, fe_class_name, proto_scope, proto_type); if (status == early_exit_status) { return status; } @@ -939,6 +1007,7 @@ static void ZEND_COLD emit_incompatible_method_error( zend_string *parent_prototype = zend_get_function_declaration(parent, parent_scope); zend_string *child_prototype = zend_get_function_declaration(child, child_scope); if (status == INHERITANCE_UNRESOLVED) { + // TODO Improve error message if first unresolved class is present in child and parent? /* Fetch the first unresolved class from registered autoloads */ zend_string *unresolved_class = NULL; ZEND_HASH_MAP_FOREACH_STR_KEY(CG(delayed_autoloads), unresolved_class) { diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c index f4f17c7ba18ef..ee42093c988b0 100644 --- a/Zend/zend_ini.c +++ b/Zend/zend_ini.c @@ -24,12 +24,17 @@ #include "zend_operators.h" #include "zend_strtod.h" #include "zend_modules.h" +#include "zend_smart_str.h" static HashTable *registered_zend_ini_directives; #define NO_VALUE_PLAINTEXT "no value" #define NO_VALUE_HTML "no value" +static inline bool zend_is_whitespace(char c) { + return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\v' || c == '\f'; +} + /* * hash_apply functions */ @@ -536,6 +541,207 @@ ZEND_API bool zend_ini_parse_bool(zend_string *str) } } +typedef enum { + ZEND_INI_PARSE_QUANTITY_SIGNED, + ZEND_INI_PARSE_QUANTITY_UNSIGNED, +} zend_ini_parse_quantity_signed_result_t; + +static zend_ulong zend_ini_parse_quantity_internal(zend_string *value, zend_ini_parse_quantity_signed_result_t signed_result, zend_string **errstr) /* {{{ */ +{ + char *digits_end = NULL; + char *str = ZSTR_VAL(value); + char *str_end = &str[ZSTR_LEN(value)]; + char *digits = str; + bool overflow = false; + zend_ulong factor; + smart_str invalid = {0}; + smart_str interpreted = {0}; + smart_str chr = {0}; + + /* Ignore leading whitespace. ZEND_STRTOL() also skips leading whitespaces, + * but we need the position of the first non-whitespace later. */ + while (digits < str_end && zend_is_whitespace(*digits)) ++digits; + + /* Ignore trailing whitespace */ + while (digits < str_end && zend_is_whitespace(*(str_end-1))) --str_end; + + if (digits == str_end) { + *errstr = NULL; + return 0; + } + + zend_ulong retval; + errno = 0; + + if (signed_result == ZEND_INI_PARSE_QUANTITY_SIGNED) { + retval = (zend_ulong) ZEND_STRTOL(digits, &digits_end, 0); + } else { + retval = ZEND_STRTOUL(digits, &digits_end, 0); + } + + if (errno == ERANGE) { + overflow = true; + } else if (signed_result == ZEND_INI_PARSE_QUANTITY_UNSIGNED) { + /* ZEND_STRTOUL() does not report a range error when the subject starts + * with a minus sign, so we check this here. Ignore "-1" as it is + * commonly used as max value, for instance in memory_limit=-1. */ + if (digits[0] == '-' && !(digits_end - digits == 2 && digits_end == str_end && digits[1] == '1')) { + overflow = true; + } + } + + if (UNEXPECTED(digits_end == digits)) { + /* No leading digits */ + + /* Escape the string to avoid null bytes and to make non-printable chars + * visible */ + smart_str_append_escaped(&invalid, ZSTR_VAL(value), ZSTR_LEN(value)); + smart_str_0(&invalid); + + *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": no valid leading digits, interpreting as \"0\" for backwards compatibility", + ZSTR_VAL(invalid.s)); + + smart_str_free(&invalid); + return 0; + } + + /* Allow for whitespace between integer portion and any suffix character */ + while (digits_end < str_end && zend_is_whitespace(*digits_end)) ++digits_end; + + /* No exponent suffix. */ + if (digits_end == str_end) { + goto end; + } + + switch (*(str_end-1)) { + case 'g': + case 'G': + factor = 1<<30; + break; + case 'm': + case 'M': + factor = 1<<20; + break; + case 'k': + case 'K': + factor = 1<<10; + break; + default: + /* Unknown suffix */ + smart_str_append_escaped(&invalid, ZSTR_VAL(value), ZSTR_LEN(value)); + smart_str_0(&invalid); + smart_str_append_escaped(&interpreted, str, digits_end - str); + smart_str_0(&interpreted); + smart_str_append_escaped(&chr, str_end-1, 1); + smart_str_0(&chr); + + *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": unknown multiplier \"%s\", interpreting as \"%s\" for backwards compatibility", + ZSTR_VAL(invalid.s), ZSTR_VAL(chr.s), ZSTR_VAL(interpreted.s)); + + smart_str_free(&invalid); + smart_str_free(&interpreted); + smart_str_free(&chr); + + return retval; + } + + if (!overflow) { + if (signed_result == ZEND_INI_PARSE_QUANTITY_SIGNED) { + zend_long sretval = (zend_long)retval; + if (sretval > 0) { + overflow = (zend_long)retval > ZEND_LONG_MAX / (zend_long)factor; + } else { + overflow = (zend_long)retval < ZEND_LONG_MIN / (zend_long)factor; + } + } else { + overflow = retval > ZEND_ULONG_MAX / factor; + } + } + + retval *= factor; + + if (UNEXPECTED(digits_end != str_end-1)) { + /* More than one character in suffix */ + smart_str_append_escaped(&invalid, ZSTR_VAL(value), ZSTR_LEN(value)); + smart_str_0(&invalid); + smart_str_append_escaped(&interpreted, str, digits_end - str); + smart_str_0(&interpreted); + smart_str_append_escaped(&chr, str_end-1, 1); + smart_str_0(&chr); + + *errstr = zend_strpprintf(0, "Invalid quantity \"%s\", interpreting as \"%s%s\" for backwards compatibility", + ZSTR_VAL(invalid.s), ZSTR_VAL(interpreted.s), ZSTR_VAL(chr.s)); + + smart_str_free(&invalid); + smart_str_free(&interpreted); + smart_str_free(&chr); + + return retval; + } + +end: + if (UNEXPECTED(overflow)) { + smart_str_append_escaped(&invalid, ZSTR_VAL(value), ZSTR_LEN(value)); + smart_str_0(&invalid); + + /* Not specifying the resulting value here because the caller may make + * additional conversions. Not specifying the allowed range + * because the caller may do narrower range checks. */ + *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": value is out of range, using overflow result for backwards compatibility", + ZSTR_VAL(invalid.s)); + + smart_str_free(&invalid); + smart_str_free(&interpreted); + smart_str_free(&chr); + + return retval; + } + + *errstr = NULL; + return retval; +} +/* }}} */ + +ZEND_API zend_long zend_ini_parse_quantity(zend_string *value, zend_string **errstr) /* {{{ */ +{ + return (zend_long) zend_ini_parse_quantity_internal(value, ZEND_INI_PARSE_QUANTITY_SIGNED, errstr); +} +/* }}} */ + +ZEND_API zend_ulong zend_ini_parse_uquantity(zend_string *value, zend_string **errstr) /* {{{ */ +{ + return zend_ini_parse_quantity_internal(value, ZEND_INI_PARSE_QUANTITY_UNSIGNED, errstr); +} +/* }}} */ + +ZEND_API zend_long zend_ini_parse_quantity_warn(zend_string *value, zend_string *setting) /* {{{ */ +{ + zend_string *errstr; + zend_long retval = zend_ini_parse_quantity(value, &errstr); + + if (errstr) { + zend_error(E_WARNING, "Invalid \"%s\" setting. %s", ZSTR_VAL(setting), ZSTR_VAL(errstr)); + zend_string_release(errstr); + } + + return retval; +} +/* }}} */ + +ZEND_API zend_ulong zend_ini_parse_uquantity_warn(zend_string *value, zend_string *setting) /* {{{ */ +{ + zend_string *errstr; + zend_ulong retval = zend_ini_parse_uquantity(value, &errstr); + + if (errstr) { + zend_error(E_WARNING, "Invalid \"%s\" setting. %s", ZSTR_VAL(setting), ZSTR_VAL(errstr)); + zend_string_release(errstr); + } + + return retval; +} +/* }}} */ + ZEND_INI_DISP(zend_ini_boolean_displayer_cb) /* {{{ */ { int value; @@ -624,14 +830,14 @@ ZEND_API ZEND_INI_MH(OnUpdateBool) /* {{{ */ ZEND_API ZEND_INI_MH(OnUpdateLong) /* {{{ */ { zend_long *p = (zend_long *) ZEND_INI_GET_ADDR(); - *p = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + *p = zend_ini_parse_quantity_warn(new_value, entry->name); return SUCCESS; } /* }}} */ ZEND_API ZEND_INI_MH(OnUpdateLongGEZero) /* {{{ */ { - zend_long tmp = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + zend_long tmp = zend_ini_parse_quantity_warn(new_value, entry->name); if (tmp < 0) { return FAILURE; } diff --git a/Zend/zend_ini.h b/Zend/zend_ini.h index 23258ec0ca8b5..a371b285764d6 100644 --- a/Zend/zend_ini.h +++ b/Zend/zend_ini.h @@ -90,6 +90,52 @@ ZEND_API char *zend_ini_string_ex(const char *name, size_t name_length, int orig ZEND_API zend_string *zend_ini_get_value(zend_string *name); ZEND_API bool zend_ini_parse_bool(zend_string *str); +/** + * Parses an ini quantity + * + * The value parameter must be a string in the form + * + * sign? digits ws* multiplier? + * + * with + * + * sign: [+-] + * digit: [0-9] + * digits: digit+ + * ws: [ \t\n\r\v\f] + * multiplier: [KMG] + * + * Leading and trailing whitespaces are ignored. + * + * If the string is empty or consists only of only whitespaces, 0 is returned. + * + * Digits is parsed as decimal unless the first digit is '0', in which case + * digits is parsed as octal. + * + * The multiplier is case-insensitive. K, M, and G multiply the quantity by + * 2**10, 2**20, and 2**30, respectively. + * + * For backwards compatibility, ill-formatted values are handled as follows: + * - No leading digits: value is treated as '0' + * - Invalid multiplier: multiplier is ignored + * - Invalid characters between digits and multiplier: invalid characters are + * ignored + * - Integer overflow: The result of the overflow is returned + * + * In any of these cases an error string is stored in *errstr (caller must + * release it), otherwise *errstr is set to NULL. + */ +ZEND_API zend_long zend_ini_parse_quantity(zend_string *value, zend_string **errstr); + +/** + * Unsigned variant of zend_ini_parse_quantity + */ +ZEND_API zend_ulong zend_ini_parse_uquantity(zend_string *value, zend_string **errstr); + +ZEND_API zend_long zend_ini_parse_quantity_warn(zend_string *value, zend_string *setting); + +ZEND_API zend_ulong zend_ini_parse_uquantity_warn(zend_string *value, zend_string *setting); + ZEND_API zend_result zend_ini_register_displayer(const char *name, uint32_t name_length, void (*displayer)(zend_ini_entry *ini_entry, int type)); ZEND_API ZEND_INI_DISP(zend_ini_boolean_displayer_cb); diff --git a/Zend/zend_ini_parser.y b/Zend/zend_ini_parser.y index 7eb3753520775..0091dbbfea81e 100644 --- a/Zend/zend_ini_parser.y +++ b/Zend/zend_ini_parser.y @@ -308,7 +308,7 @@ static void zval_ini_dtor(zval *zv) statement_list: statement_list statement - | %empty + | %empty { (void) ini_nerrs; } ; statement: diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index a333bf52a8dad..7194f70b9d471 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -272,8 +272,8 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %type lexical_var_list encaps_list %type array_pair non_empty_array_pair_list array_pair_list possible_array_pair %type isset_variable type return_type type_expr type_without_static -%type identifier type_expr_without_static union_type_without_static intersection_type_without_static -%type inline_function union_type intersection_type +%type identifier type_expr_without_static union_type_without_static_element union_type_without_static intersection_type_without_static +%type inline_function union_type_element union_type intersection_type %type attributed_statement attributed_class_statement attributed_parameter %type attribute_decl attribute attributes attribute_group namespace_declaration_name %type match match_arm_list non_empty_match_arm_list match_arm match_arm_cond_list @@ -292,7 +292,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %% /* Rules */ start: - top_statement_list { CG(ast) = $1; } + top_statement_list { CG(ast) = $1; (void) zendnerrs; } ; reserved_non_modifiers: @@ -813,9 +813,16 @@ type: | T_STATIC { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_STATIC); } ; +union_type_element: + type { $$ = $1; } + | '(' intersection_type ')' { $$ = $2; } +; + union_type: - type '|' type { $$ = zend_ast_create_list(2, ZEND_AST_TYPE_UNION, $1, $3); } - | union_type '|' type { $$ = zend_ast_list_add($1, $3); } + union_type_element '|' union_type_element + { $$ = zend_ast_create_list(2, ZEND_AST_TYPE_UNION, $1, $3); } + | union_type '|' union_type_element + { $$ = zend_ast_list_add($1, $3); } ; intersection_type: @@ -839,10 +846,15 @@ type_without_static: | name { $$ = $1; } ; +union_type_without_static_element: + type_without_static { $$ = $1; } + | '(' intersection_type_without_static ')' { $$ = $2; } +; + union_type_without_static: - type_without_static '|' type_without_static + union_type_without_static_element '|' union_type_without_static_element { $$ = zend_ast_create_list(2, ZEND_AST_TYPE_UNION, $1, $3); } - | union_type_without_static '|' type_without_static + | union_type_without_static '|' union_type_without_static_element { $$ = zend_ast_list_add($1, $3); } ; @@ -1210,8 +1222,7 @@ inline_function: | fn returns_ref backup_doc_comment '(' parameter_list ')' return_type T_DOUBLE_ARROW backup_fn_flags backup_lex_pos expr backup_fn_flags { $$ = zend_ast_create_decl(ZEND_AST_ARROW_FUNC, $2 | $12, $1, $3, - zend_string_init("{closure}", sizeof("{closure}") - 1, 0), $5, NULL, - zend_ast_create(ZEND_AST_RETURN, $11), $7, NULL); + zend_string_init("{closure}", sizeof("{closure}") - 1, 0), $5, NULL, $11, $7, NULL); ((zend_ast_decl *) $$)->lex_pos = $10; CG(extra_fn_flags) = $9; } ; @@ -1263,8 +1274,10 @@ function_call: { $$ = zend_ast_create(ZEND_AST_STATIC_CALL, $1, $3, $4); } | variable_class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list { $$ = zend_ast_create(ZEND_AST_STATIC_CALL, $1, $3, $4); } - | callable_expr argument_list - { $$ = zend_ast_create(ZEND_AST_CALL, $1, $2); } + | callable_expr { $$ = CG(zend_lineno); } argument_list { + $$ = zend_ast_create(ZEND_AST_CALL, $1, $3); + $$->lineno = $2; + } ; class_name: diff --git a/Zend/zend_mmap.h b/Zend/zend_mmap.h new file mode 100644 index 0000000000000..53eee61a7ef0c --- /dev/null +++ b/Zend/zend_mmap.h @@ -0,0 +1,44 @@ +/* + +----------------------------------------------------------------------+ + | 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: Max Kellermann | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_MMAP_H +#define ZEND_MMAP_H + +#include "zend_portability.h" + +#ifdef __linux__ +# include + +/* fallback definitions if our libc is older than the kernel */ +# ifndef PR_SET_VMA +# define PR_SET_VMA 0x53564d41 +# endif +# ifndef PR_SET_VMA_ANON_NAME +# define PR_SET_VMA_ANON_NAME 0 +# endif +#endif // __linux__ + +/** + * Set a name for the specified memory area. + * + * This feature requires Linux 5.17. + */ +static zend_always_inline void zend_mmap_set_name(const void *start, size_t len, const char *name) +{ +#ifdef __linux__ + prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (unsigned long)start, len, (unsigned long)name); +#endif +} + +#endif /* ZEND_MMAP_H */ diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 7d589356ac1d1..d0677f0fe4e96 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -622,6 +622,17 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int } } goto exit; + } else { + if (prop_info && UNEXPECTED(prop_info->flags & ZEND_ACC_READONLY)) { + if (type == BP_VAR_W || type == BP_VAR_RW) { + zend_readonly_property_indirect_modification_error(prop_info); + retval = &EG(uninitialized_zval); + goto exit; + } else if (type == BP_VAR_UNSET) { + retval = &EG(uninitialized_zval); + goto exit; + } + } } if (UNEXPECTED(Z_PROP_FLAG_P(retval) == IS_PROP_UNINIT)) { /* Skip __get() for uninitialized typed properties */ @@ -1051,9 +1062,9 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zend_object *zobj, zend_string *nam ZVAL_NULL(retval); zend_error(E_WARNING, "Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name)); } - } else if (prop_info && UNEXPECTED(prop_info->flags & ZEND_ACC_READONLY) - && !verify_readonly_initialization_access(prop_info, zobj->ce, name, "initialize")) { - retval = &EG(error_zval); + } else if (prop_info && UNEXPECTED(prop_info->flags & ZEND_ACC_READONLY)) { + /* Readonly property, delegate to read_property + write_property. */ + retval = NULL; } } else { /* we do have getter - fail and let it try again with usual get/set */ @@ -1841,7 +1852,7 @@ ZEND_API zend_string *zend_std_get_class_name(const zend_object *zobj) /* {{{ */ } /* }}} */ -ZEND_API int zend_std_cast_object_tostring(zend_object *readobj, zval *writeobj, int type) /* {{{ */ +ZEND_API zend_result zend_std_cast_object_tostring(zend_object *readobj, zval *writeobj, int type) /* {{{ */ { switch (type) { case IS_STRING: { @@ -1871,7 +1882,7 @@ ZEND_API int zend_std_cast_object_tostring(zend_object *readobj, zval *writeobj, } /* }}} */ -ZEND_API int zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only) /* {{{ */ +ZEND_API zend_result zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only) /* {{{ */ { zend_class_entry *ce = obj->ce; zval *func = zend_hash_find_known_hash(&ce->function_table, ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE)); diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index 53eef829282ce..94b7f52cba3aa 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -144,17 +144,17 @@ typedef int (*zend_object_compare_t)(zval *object1, zval *object2); /* Cast an object to some other type. * readobj and retval must point to distinct zvals. */ -typedef int (*zend_object_cast_t)(zend_object *readobj, zval *retval, int type); +typedef zend_result (*zend_object_cast_t)(zend_object *readobj, zval *retval, int type); /* updates *count to hold the number of elements present and returns SUCCESS. * Returns FAILURE if the object does not have any sense of overloaded dimensions */ -typedef int (*zend_object_count_elements_t)(zend_object *object, zend_long *count); +typedef zend_result (*zend_object_count_elements_t)(zend_object *object, zend_long *count); -typedef int (*zend_object_get_closure_t)(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only); +typedef zend_result (*zend_object_get_closure_t)(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only); typedef HashTable *(*zend_object_get_gc_t)(zend_object *object, zval **table, int *n); -typedef int (*zend_object_do_operation_t)(zend_uchar opcode, zval *result, zval *op1, zval *op2); +typedef zend_result (*zend_object_do_operation_t)(zend_uchar opcode, zval *result, zval *op1, zval *op2); struct _zend_object_handlers { /* offset of real object header (usually zero) */ @@ -209,7 +209,7 @@ ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce ZEND_API HashTable *zend_std_get_properties(zend_object *object); ZEND_API HashTable *zend_std_get_gc(zend_object *object, zval **table, int *n); ZEND_API HashTable *zend_std_get_debug_info(zend_object *object, int *is_temp); -ZEND_API int zend_std_cast_object_tostring(zend_object *object, zval *writeobj, int type); +ZEND_API zend_result zend_std_cast_object_tostring(zend_object *object, zval *writeobj, int type); ZEND_API zval *zend_std_get_property_ptr_ptr(zend_object *object, zend_string *member, int type, void **cache_slot); ZEND_API zval *zend_std_read_property(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv); ZEND_API zval *zend_std_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot); @@ -222,7 +222,7 @@ ZEND_API void zend_std_unset_dimension(zend_object *object, zval *offset); ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *method_name, const zval *key); ZEND_API zend_string *zend_std_get_class_name(const zend_object *zobj); ZEND_API int zend_std_compare_objects(zval *o1, zval *o2); -ZEND_API int zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only); +ZEND_API zend_result zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only); ZEND_API void rebuild_object_properties(zend_object *zobj); ZEND_API HashTable *zend_std_build_object_properties_array(zend_object *zobj); diff --git a/Zend/zend_observer.c b/Zend/zend_observer.c index 508cff3212a7c..8151ef74fab24 100644 --- a/Zend/zend_observer.c +++ b/Zend/zend_observer.c @@ -23,13 +23,13 @@ #include "zend_llist.h" #include "zend_vm.h" -#define ZEND_OBSERVER_DATA(op_array) \ - ZEND_OP_ARRAY_EXTENSION(op_array, zend_observer_fcall_op_array_extension) +#define ZEND_OBSERVER_DATA(function) \ + ZEND_OP_ARRAY_EXTENSION((&(function)->common), zend_observer_fcall_op_array_extension) #define ZEND_OBSERVER_NOT_OBSERVED ((void *) 2) -#define ZEND_OBSERVABLE_FN(fn_flags) \ - (!(fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) +#define ZEND_OBSERVABLE_FN(function) \ + (ZEND_MAP_PTR(function->common.run_time_cache) && !(function->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) zend_llist zend_observers_fcall_list; zend_llist zend_observer_error_callbacks; @@ -87,11 +87,6 @@ ZEND_API void zend_observer_activate(void) current_observed_frame = NULL; } -ZEND_API void zend_observer_deactivate(void) -{ - // now empty and unused, but kept for ABI compatibility -} - ZEND_API void zend_observer_shutdown(void) { zend_llist_destroy(&zend_observers_fcall_list); @@ -105,14 +100,11 @@ static void zend_observer_fcall_install(zend_execute_data *execute_data) { zend_llist *list = &zend_observers_fcall_list; zend_function *function = execute_data->func; - zend_op_array *op_array = &function->op_array; - - ZEND_ASSERT(function->type != ZEND_INTERNAL_FUNCTION); - ZEND_ASSERT(RUN_TIME_CACHE(op_array)); - zend_observer_fcall_begin_handler *begin_handlers = (zend_observer_fcall_begin_handler *)&ZEND_OBSERVER_DATA(op_array); + ZEND_ASSERT(RUN_TIME_CACHE(&function->common)); + zend_observer_fcall_begin_handler *begin_handlers = (zend_observer_fcall_begin_handler *)&ZEND_OBSERVER_DATA(function); zend_observer_fcall_end_handler *end_handlers = (zend_observer_fcall_end_handler *)begin_handlers + list->count, *end_handlers_start = end_handlers; - + *begin_handlers = ZEND_OBSERVER_NOT_OBSERVED; *end_handlers = ZEND_OBSERVER_NOT_OBSERVED; @@ -127,7 +119,7 @@ static void zend_observer_fcall_install(zend_execute_data *execute_data) *(end_handlers++) = handlers.end; } } - + // end handlers are executed in reverse order for (--end_handlers; end_handlers_start < end_handlers; --end_handlers, ++end_handlers_start) { zend_observer_fcall_end_handler tmp = *end_handlers; @@ -136,20 +128,78 @@ static void zend_observer_fcall_install(zend_execute_data *execute_data) } } +static bool zend_observer_remove_handler(void **first_handler, void *old_handler) { + size_t registered_observers = zend_observers_fcall_list.count; + + void **last_handler = first_handler + registered_observers - 1; + for (void **cur_handler = first_handler; cur_handler <= last_handler; ++cur_handler) { + if (*cur_handler == old_handler) { + if (registered_observers == 1 || (cur_handler == first_handler && cur_handler[1] == NULL)) { + *cur_handler = ZEND_OBSERVER_NOT_OBSERVED; + } else { + if (cur_handler != last_handler) { + memmove(cur_handler, cur_handler + 1, sizeof(cur_handler) * (last_handler - cur_handler)); + } else { + *last_handler = NULL; + } + } + return true; + } + } + return false; +} + +ZEND_API void zend_observer_add_begin_handler(zend_function *function, zend_observer_fcall_begin_handler begin) { + size_t registered_observers = zend_observers_fcall_list.count; + zend_observer_fcall_begin_handler *first_handler = (void *)&ZEND_OBSERVER_DATA(function), *last_handler = first_handler + registered_observers - 1; + if (*first_handler == ZEND_OBSERVER_NOT_OBSERVED) { + *first_handler = begin; + } else { + for (zend_observer_fcall_begin_handler *cur_handler = first_handler + 1; cur_handler <= last_handler; ++cur_handler) { + if (*cur_handler == NULL) { + *cur_handler = begin; + return; + } + } + // there's no space for new handlers, then it's forbidden to call this function + ZEND_UNREACHABLE(); + } +} + +ZEND_API bool zend_observer_remove_begin_handler(zend_function *function, zend_observer_fcall_begin_handler begin) { + return zend_observer_remove_handler((void **)&ZEND_OBSERVER_DATA(function), begin); +} + +ZEND_API void zend_observer_add_end_handler(zend_function *function, zend_observer_fcall_end_handler end) { + size_t registered_observers = zend_observers_fcall_list.count; + zend_observer_fcall_end_handler *end_handler = (zend_observer_fcall_end_handler *)&ZEND_OBSERVER_DATA(function) + registered_observers; + // to allow to preserve the invariant that end handlers are in reverse order of begin handlers, push the new end handler in front + if (*end_handler != ZEND_OBSERVER_NOT_OBSERVED) { + // there's no space for new handlers, then it's forbidden to call this function + ZEND_ASSERT(end_handler[registered_observers - 1] == NULL); + memmove(end_handler + 1, end_handler, registered_observers - 1); + } + *end_handler = end; +} + +ZEND_API bool zend_observer_remove_end_handler(zend_function *function, zend_observer_fcall_end_handler end) { + size_t registered_observers = zend_observers_fcall_list.count; + return zend_observer_remove_handler((void **)&ZEND_OBSERVER_DATA(function) + registered_observers, end); +} + static void ZEND_FASTCALL _zend_observe_fcall_begin(zend_execute_data *execute_data) { if (!ZEND_OBSERVER_ENABLED) { return; } - zend_op_array *op_array = &execute_data->func->op_array; - uint32_t fn_flags = op_array->fn_flags; + zend_function *function = execute_data->func; - if (!ZEND_OBSERVABLE_FN(fn_flags)) { + if (!ZEND_OBSERVABLE_FN(function)) { return; } - zend_observer_fcall_begin_handler *handler = (zend_observer_fcall_begin_handler *)&ZEND_OBSERVER_DATA(op_array); + zend_observer_fcall_begin_handler *handler = (zend_observer_fcall_begin_handler *)&ZEND_OBSERVER_DATA(function); if (!*handler) { zend_observer_fcall_install(execute_data); } @@ -189,11 +239,11 @@ ZEND_API void ZEND_FASTCALL zend_observer_fcall_begin(zend_execute_data *execute static inline bool zend_observer_is_skipped_frame(zend_execute_data *execute_data) { zend_function *func = execute_data->func; - if (!func || func->type == ZEND_INTERNAL_FUNCTION || !ZEND_OBSERVABLE_FN(func->common.fn_flags)) { + if (!func || !ZEND_OBSERVABLE_FN(func)) { return true; } - zend_observer_fcall_end_handler end_handler = (&ZEND_OBSERVER_DATA(&func->op_array))[zend_observers_fcall_list.count]; + zend_observer_fcall_end_handler end_handler = (&ZEND_OBSERVER_DATA(func))[zend_observers_fcall_list.count]; if (end_handler == NULL || end_handler == ZEND_OBSERVER_NOT_OBSERVED) { return true; } @@ -205,12 +255,11 @@ ZEND_API void ZEND_FASTCALL zend_observer_fcall_end(zend_execute_data *execute_d { zend_function *func = execute_data->func; - if (!ZEND_OBSERVER_ENABLED - || !ZEND_OBSERVABLE_FN(func->common.fn_flags)) { + if (!ZEND_OBSERVER_ENABLED || !ZEND_OBSERVABLE_FN(func)) { return; } - zend_observer_fcall_end_handler *handler = (zend_observer_fcall_end_handler *)&ZEND_OBSERVER_DATA(&func->op_array) + zend_observers_fcall_list.count; + zend_observer_fcall_end_handler *handler = (zend_observer_fcall_end_handler *)&ZEND_OBSERVER_DATA(func) + zend_observers_fcall_list.count; // TODO: Fix exceptions from generators // ZEND_ASSERT(fcall_data); if (!*handler || *handler == ZEND_OBSERVER_NOT_OBSERVED) { @@ -238,7 +287,7 @@ ZEND_API void zend_observer_fcall_end_all(void) { zend_execute_data *ex = current_observed_frame; while (ex != NULL) { - if (ex->func && ex->func->type != ZEND_INTERNAL_FUNCTION) { + if (ex->func) { zend_observer_fcall_end(ex, NULL); } ex = ex->prev_execute_data; diff --git a/Zend/zend_observer.h b/Zend/zend_observer.h index b43ff1e4f6557..ebd5c0ce62a01 100644 --- a/Zend/zend_observer.h +++ b/Zend/zend_observer.h @@ -56,10 +56,16 @@ typedef zend_observer_fcall_handlers (*zend_observer_fcall_init)(zend_execute_da // Call during minit/startup ONLY ZEND_API void zend_observer_fcall_register(zend_observer_fcall_init); +// Call during runtime, but only if you have used zend_observer_fcall_register. +// You must not have more than one begin and one end handler active at the same time. Remove the old one first, if there is an existing one. +ZEND_API void zend_observer_add_begin_handler(zend_function *function, zend_observer_fcall_begin_handler begin); +ZEND_API bool zend_observer_remove_begin_handler(zend_function *function, zend_observer_fcall_begin_handler begin); +ZEND_API void zend_observer_add_end_handler(zend_function *function, zend_observer_fcall_end_handler end); +ZEND_API bool zend_observer_remove_end_handler(zend_function *function, zend_observer_fcall_end_handler end); + ZEND_API void zend_observer_startup(void); // Called by engine before MINITs ZEND_API void zend_observer_post_startup(void); // Called by engine after MINITs ZEND_API void zend_observer_activate(void); -ZEND_API void zend_observer_deactivate(void); ZEND_API void zend_observer_shutdown(void); ZEND_API void ZEND_FASTCALL zend_observer_fcall_begin( diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 86cf4c6f9f118..93f70462ad8d3 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -275,6 +275,11 @@ ZEND_API void zend_cleanup_mutable_class_data(zend_class_entry *ce) mutable_data->default_properties_table = NULL; } + if (mutable_data->backed_enum_table) { + zend_hash_release(mutable_data->backed_enum_table); + mutable_data->backed_enum_table = NULL; + } + ZEND_MAP_PTR_SET_IMM(ce->mutable_data, NULL); } } diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index a35edc01501c0..3690162418fa3 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -118,7 +118,7 @@ ZEND_API const unsigned char zend_toupper_map[256] = { 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef, -0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff +0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff }; @@ -136,7 +136,7 @@ ZEND_API const unsigned char zend_toupper_map[256] = { zend_binary_strncasecmp */ -ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len) /* {{{ */ +static zend_long ZEND_FASTCALL zend_atol_internal(const char *str, size_t str_len) /* {{{ */ { if (!str_len) { str_len = strlen(str); @@ -168,9 +168,14 @@ ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len) /* { } /* }}} */ +ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len) +{ + return zend_atol_internal(str, str_len); +} + ZEND_API int ZEND_FASTCALL zend_atoi(const char *str, size_t str_len) { - return (int) zend_atol(str, str_len); + return (int) zend_atol_internal(str, str_len); } /* {{{ convert_object_to_type: dst will be either ctype or UNDEF */ diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 346706d22beae..de02a406d575e 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -468,8 +468,11 @@ ZEND_API int ZEND_FASTCALL zend_compare_symbol_tables(HashTable *ht1, HashTable ZEND_API int ZEND_FASTCALL zend_compare_arrays(zval *a1, zval *a2); ZEND_API int ZEND_FASTCALL zend_compare_objects(zval *o1, zval *o2); -ZEND_API int ZEND_FASTCALL zend_atoi(const char *str, size_t str_len); -ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len); +/** Deprecatd in favor of ZEND_STRTOL() */ +ZEND_ATTRIBUTE_DEPRECATED ZEND_API int ZEND_FASTCALL zend_atoi(const char *str, size_t str_len); + +/** Deprecatd in favor of ZEND_STRTOL() */ +ZEND_ATTRIBUTE_DEPRECATED ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len); #define convert_to_null_ex(zv) convert_to_null(zv) #define convert_to_boolean_ex(zv) convert_to_boolean(zv) diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index 51f16f88b0ce4..a2cee98425e1f 100644 --- a/Zend/zend_portability.h +++ b/Zend/zend_portability.h @@ -214,6 +214,8 @@ char *alloca(); #if ZEND_GCC_VERSION >= 2096 || __has_attribute(__malloc__) # define ZEND_ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) +#elif defined(ZEND_WIN32) +# define ZEND_ATTRIBUTE_MALLOC __declspec(restrict) #else # define ZEND_ATTRIBUTE_MALLOC #endif @@ -522,7 +524,7 @@ extern "C++" { #ifdef __SSSE3__ /* Instructions compiled directly. */ # define ZEND_INTRIN_SSSE3_NATIVE 1 -#elif (defined(HAVE_FUNC_ATTRIBUTE_TARGET) && defined(PHP_HAVE_SSSE3)) || defined(ZEND_WIN32) +#elif (defined(HAVE_FUNC_ATTRIBUTE_TARGET) && defined(PHP_HAVE_SSSE3)) || (defined(ZEND_WIN32) && (!defined(_M_ARM64))) /* Function resolved by ifunc or MINIT. */ # define ZEND_INTRIN_SSSE3_RESOLVER 1 #endif @@ -547,7 +549,7 @@ extern "C++" { #ifdef __SSE4_2__ /* Instructions compiled directly. */ # define ZEND_INTRIN_SSE4_2_NATIVE 1 -#elif (defined(HAVE_FUNC_ATTRIBUTE_TARGET) && defined(PHP_HAVE_SSE4_2)) || defined(ZEND_WIN32) +#elif (defined(HAVE_FUNC_ATTRIBUTE_TARGET) && defined(PHP_HAVE_SSE4_2)) || (defined(ZEND_WIN32) && (!defined(_M_ARM64))) /* Function resolved by ifunc or MINIT. */ # define ZEND_INTRIN_SSE4_2_RESOLVER 1 #endif @@ -572,7 +574,7 @@ extern "C++" { #ifdef __PCLMUL__ /* Instructions compiled directly. */ # define ZEND_INTRIN_PCLMUL_NATIVE 1 -#elif (defined(HAVE_FUNC_ATTRIBUTE_TARGET) && defined(PHP_HAVE_PCLMUL)) || defined(ZEND_WIN32) +#elif (defined(HAVE_FUNC_ATTRIBUTE_TARGET) && defined(PHP_HAVE_PCLMUL)) || (defined(ZEND_WIN32) && (!defined(_M_ARM64))) /* Function resolved by ifunc or MINIT. */ # define ZEND_INTRIN_PCLMUL_RESOLVER 1 #endif @@ -598,7 +600,7 @@ extern "C++" { #if defined(ZEND_INTRIN_SSE4_2_NATIVE) && defined(ZEND_INTRIN_PCLMUL_NATIVE) /* Instructions compiled directly. */ # define ZEND_INTRIN_SSE4_2_PCLMUL_NATIVE 1 -#elif (defined(HAVE_FUNC_ATTRIBUTE_TARGET) && defined(PHP_HAVE_SSE4_2) && defined(PHP_HAVE_PCLMUL)) || defined(ZEND_WIN32) +#elif (defined(HAVE_FUNC_ATTRIBUTE_TARGET) && defined(PHP_HAVE_SSE4_2) && defined(PHP_HAVE_PCLMUL)) || (defined(ZEND_WIN32) && (!defined(_M_ARM64))) /* Function resolved by ifunc or MINIT. */ # define ZEND_INTRIN_SSE4_2_PCLMUL_RESOLVER 1 #endif @@ -623,7 +625,7 @@ extern "C++" { #ifdef __AVX2__ # define ZEND_INTRIN_AVX2_NATIVE 1 -#elif (defined(HAVE_FUNC_ATTRIBUTE_TARGET) && defined(PHP_HAVE_AVX2)) || defined(ZEND_WIN32) +#elif (defined(HAVE_FUNC_ATTRIBUTE_TARGET) && defined(PHP_HAVE_AVX2)) || (defined(ZEND_WIN32) && (!defined(_M_ARM64))) # define ZEND_INTRIN_AVX2_RESOLVER 1 #endif diff --git a/Zend/zend_ptr_stack.h b/Zend/zend_ptr_stack.h index fd4b59d15178c..1126da5800d1b 100644 --- a/Zend/zend_ptr_stack.h +++ b/Zend/zend_ptr_stack.h @@ -48,7 +48,7 @@ END_EXTERN_C() do { \ stack->max += PTR_STACK_BLOCK_SIZE; \ } while (stack->top+count > stack->max); \ - stack->elements = (void **) perealloc(stack->elements, (sizeof(void *) * (stack->max)), stack->persistent); \ + stack->elements = (void **) safe_perealloc(stack->elements, sizeof(void *), (stack->max), 0, stack->persistent); \ stack->top_element = stack->elements+stack->top; \ } diff --git a/Zend/zend_smart_str.h b/Zend/zend_smart_str.h index 80fe28615bf07..cf28016993f74 100644 --- a/Zend/zend_smart_str.h +++ b/Zend/zend_smart_str.h @@ -25,6 +25,10 @@ smart_str_appendl_ex((dest), (src), strlen(src), (what)) #define smart_str_appends(dest, src) \ smart_str_appendl((dest), (src), strlen(src)) +#define smart_str_extract(dest) \ + smart_str_extract_ex((dest), 0) +#define smart_str_trim_to_size(dest) \ + smart_str_trim_to_size_ex((dest), 0) #define smart_str_extend(dest, len) \ smart_str_extend_ex((dest), (len), 0) #define smart_str_appendc(dest, c) \ @@ -101,10 +105,19 @@ static zend_always_inline size_t smart_str_get_len(smart_str *str) { return str->s ? ZSTR_LEN(str->s) : 0; } -static zend_always_inline zend_string *smart_str_extract(smart_str *str) { +static zend_always_inline void smart_str_trim_to_size_ex(smart_str *str, bool persistent) +{ + if (str->s && str->a > ZSTR_LEN(str->s)) { + str->s = zend_string_realloc(str->s, ZSTR_LEN(str->s), persistent); + str->a = ZSTR_LEN(str->s); + } +} + +static zend_always_inline zend_string *smart_str_extract_ex(smart_str *str, bool persistent) { if (str->s) { zend_string *res; smart_str_0(str); + smart_str_trim_to_size_ex(str, persistent); res = str->s; str->s = NULL; return res; diff --git a/Zend/zend_smart_str_public.h b/Zend/zend_smart_str_public.h index 8b37db5bd1e4f..e81a6839b3bbb 100644 --- a/Zend/zend_smart_str_public.h +++ b/Zend/zend_smart_str_public.h @@ -18,6 +18,7 @@ #define ZEND_SMART_STR_PUBLIC_H typedef struct { + /** See smart_str_extract() */ zend_string *s; size_t a; } smart_str; diff --git a/Zend/zend_string.h b/Zend/zend_string.h index ef67daad74bbf..ed59ef82a14fe 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -592,6 +592,7 @@ EMPTY_SWITCH_DEFAULT_CASE() _(ZEND_STR_AUTOGLOBAL_ENV, "_ENV") \ _(ZEND_STR_AUTOGLOBAL_REQUEST, "_REQUEST") \ _(ZEND_STR_COUNT, "count") \ + _(ZEND_STR_SENSITIVEPARAMETER, "SensitiveParameter") \ typedef enum _zend_known_string_id { diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 908a2c769a909..df64541749d4c 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -280,6 +280,9 @@ typedef struct { #define ZEND_TYPE_INIT_UNION(ptr, extra_flags) \ { (void *) (ptr), (_ZEND_TYPE_LIST_BIT|_ZEND_TYPE_UNION_BIT) | (extra_flags) } +#define ZEND_TYPE_INIT_INTERSECTION(ptr, extra_flags) \ + { (void *) (ptr), (_ZEND_TYPE_LIST_BIT|_ZEND_TYPE_INTERSECTION_BIT) | (extra_flags) } + #define ZEND_TYPE_INIT_CLASS(class_name, allow_null, extra_flags) \ ZEND_TYPE_INIT_PTR(class_name, _ZEND_TYPE_NAME_BIT, allow_null, extra_flags) @@ -740,6 +743,7 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) { #define ZSTR_SET_CE_CACHE_EX(s, ce, validate) do { \ if (!(validate) || ZSTR_VALID_CE_CACHE(s)) { \ + ZEND_ASSERT((validate) || ZSTR_VALID_CE_CACHE(s)); \ SET_CE_CACHE(GC_REFCOUNT(s), ce); \ } \ } while (0) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 54cc5dfe3a923..df042aa8f3199 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -405,7 +405,7 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_ } } else if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -1998,9 +1998,9 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, C #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) { + if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_DISPATCH_TO_HELPER(zend_use_tmp_in_write_context_helper); - } + } ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_DIM_W); } else { if (OP2_TYPE == IS_UNUSED) { @@ -2036,7 +2036,7 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST if (OP1_TYPE == IS_CONST || (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - do { + do { if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { @@ -2084,9 +2084,9 @@ ZEND_VM_C_LABEL(fetch_obj_r_fast_copy): Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) { ZEND_VM_C_GOTO(fetch_obj_r_copy); @@ -2248,9 +2248,9 @@ ZEND_VM_C_LABEL(fetch_obj_is_fast_copy): Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) { ZEND_VM_C_GOTO(fetch_obj_is_copy); @@ -3161,7 +3161,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP } } else if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -3503,9 +3503,9 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV, if (OP2_TYPE == IS_CONST && EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else { - zend_object *orig_obj = obj; + zend_object *orig_obj = obj; if (OP2_TYPE == IS_CONST) { function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); @@ -3908,7 +3908,7 @@ ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM|CACHE_SLOT) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL)) +ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL,OBSERVER)) { USE_OPLINE zend_execute_data *call = EX(call); @@ -3929,6 +3929,7 @@ ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL)) ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + ZEND_OBSERVER_FCALL_BEGIN(call); fbc->internal_function.handler(call, ret); #if ZEND_DEBUG @@ -3943,6 +3944,7 @@ ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL)) zend_verify_internal_func_info(call->func, ret); } #endif + ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret); EG(current_execute_data) = execute_data; zend_vm_stack_free_args(call); @@ -4048,6 +4050,7 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL,OBSERVER)) ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + ZEND_OBSERVER_FCALL_BEGIN(call); fbc->internal_function.handler(call, ret); #if ZEND_DEBUG @@ -4062,6 +4065,7 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL,OBSERVER)) zend_verify_internal_func_info(call->func, ret); } #endif + ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret); EG(current_execute_data) = execute_data; @@ -4153,6 +4157,7 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL,OBSERVER)) ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + ZEND_OBSERVER_FCALL_BEGIN(call); if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ fbc->internal_function.handler(call, ret); @@ -4172,6 +4177,7 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL,OBSERVER)) zend_verify_internal_func_info(call->func, ret); } #endif + ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret); EG(current_execute_data) = execute_data; @@ -5782,7 +5788,7 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) do { if (OP1_TYPE == IS_CONST || (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { - if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) { + if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) { obj = Z_REFVAL_P(obj); if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) { break; @@ -6281,7 +6287,8 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL, SPEC(OBSER } } else if (new_op_array->last == 1 && new_op_array->opcodes[0].opcode == ZEND_RETURN - && new_op_array->opcodes[0].op1_type == IS_CONST) { + && new_op_array->opcodes[0].op1_type == IS_CONST + && EXPECTED(zend_execute_ex == execute_ex)) { if (RETURN_VALUE_USED(opline)) { const zend_op *op = new_op_array->opcodes; @@ -6300,7 +6307,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL, SPEC(OBSER new_op_array->scope = EX(func)->op_array.scope; call = zend_vm_stack_push_call_frame( - (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, + (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, Z_PTR(EX(This))); @@ -7751,7 +7758,9 @@ ZEND_VM_HANDLER(105, ZEND_TICKS, ANY, ANY, NUM) EG(ticks_count) = 0; if (zend_ticks_function) { SAVE_OPLINE(); + zend_fiber_switch_block(); zend_ticks_function(opline->extended_value); + zend_fiber_switch_unblock(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } @@ -8126,7 +8135,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMPVAR|CV|UNUSED } } else if (OP1_TYPE == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); FREE_OP1_IF_VAR(); } else { @@ -8361,9 +8370,9 @@ ZEND_VM_HOT_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST, CACHE_SLOT) Bucket *p = (Bucket*)((char*)EG(symbol_table).arData + idx); if (EXPECTED(p->key == varname) || - (EXPECTED(p->h == ZSTR_H(varname)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, varname)))) { + (EXPECTED(p->h == ZSTR_H(varname)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, varname)))) { value = (zval*)p; /* value = &p->val; */ ZEND_VM_C_GOTO(check_indirect); @@ -8707,6 +8716,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY, SPEC(OBSERVER)) } ZVAL_NULL(ret); + ZEND_OBSERVER_FCALL_BEGIN(call); if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ fbc->internal_function.handler(call, ret); @@ -8726,6 +8736,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY, SPEC(OBSERVER)) zend_verify_internal_func_info(call->func, ret); } #endif + ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret); EG(current_execute_data) = call->prev_execute_data; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 76e4aace61471..b3a48b80f480b 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1350,6 +1350,70 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV ZEND_VM_CONTINUE(); } +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_execute_data *call = EX(call); + zend_function *fbc = call->func; + zval *ret; + zval retval; + + SAVE_OPLINE(); + EX(call) = call->prev_execute_data; + + call->prev_execute_data = execute_data; + EG(current_execute_data) = call; + +#if ZEND_DEBUG + bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif + + ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); + + zend_observer_fcall_begin(call); + fbc->internal_function.handler(call, ret); + +#if ZEND_DEBUG + if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } + ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || + zend_verify_internal_return_type(call->func, ret)); + ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) + ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); + zend_verify_internal_func_info(call->func, ret); + } +#endif + zend_observer_fcall_end(call, EG(exception) ? NULL : ret); + + EG(current_execute_data) = execute_data; + zend_vm_stack_free_args(call); + + uint32_t call_info = ZEND_CALL_INFO(call); + if (UNEXPECTED(call_info & (ZEND_CALL_HAS_EXTRA_NAMED_PARAMS|ZEND_CALL_ALLOCATED))) { + if (call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { + zend_free_extra_named_params(call->extra_named_params); + } + zend_vm_stack_free_call_frame_ex(call_info, call); + } else { + EG(vm_stack_top) = (zval*)call; + } + + if (!RETURN_VALUE_USED(opline)) { + i_zval_ptr_dtor(ret); + } + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION(); + } + + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); +} + static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -1666,6 +1730,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_ ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + zend_observer_fcall_begin(call); fbc->internal_function.handler(call, ret); #if ZEND_DEBUG @@ -1680,6 +1745,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_ zend_verify_internal_func_info(call->func, ret); } #endif + zend_observer_fcall_end(call, EG(exception) ? NULL : ret); EG(current_execute_data) = execute_data; @@ -1989,6 +2055,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_OBS ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + zend_observer_fcall_begin(call); if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ fbc->internal_function.handler(call, ret); @@ -2008,6 +2075,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_OBS zend_verify_internal_func_info(call->func, ret); } #endif + zend_observer_fcall_end(call, EG(exception) ? NULL : ret); EG(current_execute_data) = execute_data; @@ -2996,7 +3064,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TICKS_SPEC_HANDLER(ZEND_OPCODE EG(ticks_count) = 0; if (zend_ticks_function) { SAVE_OPLINE(); + zend_fiber_switch_block(); zend_ticks_function(opline->extended_value); + zend_fiber_switch_unblock(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } @@ -3340,6 +3410,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z } ZVAL_NULL(ret); + if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ fbc->internal_function.handler(call, ret); @@ -3477,6 +3548,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_ } ZVAL_NULL(ret); + zend_observer_fcall_begin(call); if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ fbc->internal_function.handler(call, ret); @@ -3496,6 +3568,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_ zend_verify_internal_func_info(call->func, ret); } #endif + zend_observer_fcall_end(call, EG(exception) ? NULL : ret); EG(current_execute_data) = call->prev_execute_data; @@ -4675,7 +4748,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ do { if (IS_CONST == IS_CONST || (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { - if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) { + if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) { obj = Z_REFVAL_P(obj); if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) { break; @@ -4843,7 +4916,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN } } else if (new_op_array->last == 1 && new_op_array->opcodes[0].opcode == ZEND_RETURN - && new_op_array->opcodes[0].op1_type == IS_CONST) { + && new_op_array->opcodes[0].op1_type == IS_CONST + && EXPECTED(zend_execute_ex == execute_ex)) { if (RETURN_VALUE_USED(opline)) { const zend_op *op = new_op_array->opcodes; @@ -4862,7 +4936,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN new_op_array->scope = EX(func)->op_array.scope; call = zend_vm_stack_push_call_frame( - (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, + (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, Z_PTR(EX(This))); @@ -4925,7 +4999,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_ } } else if (new_op_array->last == 1 && new_op_array->opcodes[0].opcode == ZEND_RETURN - && new_op_array->opcodes[0].op1_type == IS_CONST) { + && new_op_array->opcodes[0].op1_type == IS_CONST + && EXPECTED(zend_execute_ex == execute_ex)) { if (RETURN_VALUE_USED(opline)) { const zend_op *op = new_op_array->opcodes; @@ -4944,7 +5019,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_ new_op_array->scope = EX(func)->op_array.scope; call = zend_vm_stack_push_call_frame( - (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, + (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, Z_PTR(EX(This))); @@ -6206,9 +6281,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_AR #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + } ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { if (IS_CONST == IS_UNUSED) { @@ -6229,7 +6304,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ if (IS_CONST == IS_CONST || (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - do { + do { if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { @@ -6277,9 +6352,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -6403,9 +6478,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -6521,7 +6596,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_ } } else if (IS_CONST != IS_CONST && IS_CONST != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -6694,9 +6769,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ if (IS_CONST == IS_CONST && EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else { - zend_object *orig_obj = obj; + zend_object *orig_obj = obj; if (IS_CONST == IS_CONST) { function_name = RT_CONSTANT(opline, opline->op2); @@ -7496,7 +7571,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER } } else if (IS_CONST == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { @@ -8434,7 +8509,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL } } else if (IS_CONST != IS_CONST && IS_CONST != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -8543,9 +8618,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_ #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + } ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { @@ -8566,7 +8641,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ if (IS_CONST == IS_CONST || (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - do { + do { if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { @@ -8614,9 +8689,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -8740,9 +8815,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -8858,7 +8933,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_ } } else if (IS_CONST != IS_CONST && IS_CONST != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -9031,9 +9106,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else { - zend_object *orig_obj = obj; + zend_object *orig_obj = obj; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); @@ -9642,7 +9717,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLE } } else if (IS_CONST == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { @@ -9832,9 +9907,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_ #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + } ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { if (IS_UNUSED == IS_UNUSED) { @@ -10485,7 +10560,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE } } else if (IS_CONST == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { @@ -10799,7 +10874,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z } } else if (IS_CONST != IS_CONST && IS_CONST != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -10908,9 +10983,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_ #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + } ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { if (IS_CV == IS_UNUSED) { @@ -10931,7 +11006,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ if (IS_CONST == IS_CONST || (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - do { + do { if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { @@ -10979,9 +11054,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -11105,9 +11180,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -11223,7 +11298,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND } } else if (IS_CONST != IS_CONST && IS_CONST != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -11396,9 +11471,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ if (IS_CV == IS_CONST && EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else { - zend_object *orig_obj = obj; + zend_object *orig_obj = obj; if (IS_CV == IS_CONST) { function_name = EX_VAR(opline->op2.var); @@ -12005,7 +12080,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE } } else if (IS_CONST == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { @@ -14369,7 +14444,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND do { if ((IS_TMP_VAR|IS_VAR) == IS_CONST || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) { obj = Z_REFVAL_P(obj); if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) { break; @@ -14445,7 +14520,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA } } else if (new_op_array->last == 1 && new_op_array->opcodes[0].opcode == ZEND_RETURN - && new_op_array->opcodes[0].op1_type == IS_CONST) { + && new_op_array->opcodes[0].op1_type == IS_CONST + && EXPECTED(zend_execute_ex == execute_ex)) { if (RETURN_VALUE_USED(opline)) { const zend_op *op = new_op_array->opcodes; @@ -14464,7 +14540,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA new_op_array->scope = EX(func)->op_array.scope; call = zend_vm_stack_push_call_frame( - (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, + (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, Z_PTR(EX(This))); @@ -14828,7 +14904,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -15303,7 +15379,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ if ((IS_TMP_VAR|IS_VAR) == IS_CONST || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - do { + do { if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { @@ -15351,9 +15427,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -15477,9 +15553,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -15566,7 +15642,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_ } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -15739,9 +15815,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C if (IS_CONST == IS_CONST && EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else { - zend_object *orig_obj = obj; + zend_object *orig_obj = obj; if (IS_CONST == IS_CONST) { function_name = RT_CONSTANT(opline, opline->op2); @@ -16264,7 +16340,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -16739,7 +16815,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR if ((IS_TMP_VAR|IS_VAR) == IS_CONST || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - do { + do { if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { @@ -16787,9 +16863,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -16913,9 +16989,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVA Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -17002,7 +17078,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -17175,9 +17251,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else { - zend_object *orig_obj = obj; + zend_object *orig_obj = obj; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); @@ -17951,7 +18027,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER( } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -18064,7 +18140,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN if ((IS_TMP_VAR|IS_VAR) == IS_CONST || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - do { + do { if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { @@ -18112,9 +18188,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -18238,9 +18314,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HA Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -18327,7 +18403,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -18500,9 +18576,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C if (IS_CV == IS_CONST && EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else { - zend_object *orig_obj = obj; + zend_object *orig_obj = obj; if (IS_CV == IS_CONST) { function_name = EX_VAR(opline->op2.var); @@ -19467,9 +19543,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CO #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + } ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { if (IS_CONST == IS_UNUSED) { @@ -19811,7 +19887,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z } } else if (IS_TMP_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { @@ -19944,9 +20020,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TM #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + } ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { @@ -20251,7 +20327,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER( } } else if (IS_TMP_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { @@ -20371,9 +20447,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UN #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + } ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { if (IS_UNUSED == IS_UNUSED) { @@ -20712,7 +20788,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( } } else if (IS_TMP_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { @@ -20805,9 +20881,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + } ZEND_VM_TAIL_CALL(ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { if (IS_CV == IS_UNUSED) { @@ -21112,7 +21188,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND } } else if (IS_TMP_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { @@ -22801,9 +22877,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CO #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + } ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { if (IS_CONST == IS_UNUSED) { @@ -24979,7 +25055,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z } } else if (IS_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { @@ -25506,9 +25582,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TM #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + } ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { @@ -27277,7 +27353,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER( } } else if (IS_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { @@ -27671,9 +27747,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UN #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + } ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { if (IS_UNUSED == IS_UNUSED) { @@ -29176,7 +29252,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( } } else if (IS_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { @@ -29714,9 +29790,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + } ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { if (IS_CV == IS_UNUSED) { @@ -31555,7 +31631,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND } } else if (IS_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { @@ -31760,7 +31836,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND do { if (IS_UNUSED == IS_CONST || (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { - if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) { + if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) { obj = Z_REFVAL_P(obj); if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) { break; @@ -32111,7 +32187,7 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R if (IS_UNUSED == IS_CONST || (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - do { + do { if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { @@ -32159,9 +32235,9 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -32328,9 +32404,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -33177,9 +33253,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S if (IS_CONST == IS_CONST && EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else { - zend_object *orig_obj = obj; + zend_object *orig_obj = obj; if (IS_CONST == IS_CONST) { function_name = RT_CONSTANT(opline, opline->op2); @@ -33686,7 +33762,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE } } else if (IS_UNUSED == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { @@ -33983,7 +34059,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR if (IS_UNUSED == IS_CONST || (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - do { + do { if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { @@ -34031,9 +34107,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -34195,9 +34271,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVA Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -35045,9 +35121,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else { - zend_object *orig_obj = obj; + zend_object *orig_obj = obj; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); @@ -35430,7 +35506,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMPVAR_HANDL } } else if (IS_UNUSED == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { @@ -35972,7 +36048,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL } } else if (IS_UNUSED == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { @@ -36460,7 +36536,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN if (IS_UNUSED == IS_CONST || (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - do { + do { if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { @@ -36508,9 +36584,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -36672,9 +36748,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HA Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -37521,9 +37597,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C if (IS_CV == IS_CONST && EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else { - zend_object *orig_obj = obj; + zend_object *orig_obj = obj; if (IS_CV == IS_CONST) { function_name = EX_VAR(opline->op2.var); @@ -37905,7 +37981,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z } } else if (IS_UNUSED == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { @@ -38662,7 +38738,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC do { if (IS_CV == IS_CONST || (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { - if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) { + if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) { obj = Z_REFVAL_P(obj); if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) { break; @@ -38830,7 +38906,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE } } else if (new_op_array->last == 1 && new_op_array->opcodes[0].opcode == ZEND_RETURN - && new_op_array->opcodes[0].op1_type == IS_CONST) { + && new_op_array->opcodes[0].op1_type == IS_CONST + && EXPECTED(zend_execute_ex == execute_ex)) { if (RETURN_VALUE_USED(opline)) { const zend_op *op = new_op_array->opcodes; @@ -38849,7 +38926,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE new_op_array->scope = EX(func)->op_array.scope; call = zend_vm_stack_push_call_frame( - (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, + (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, Z_PTR(EX(This))); @@ -39701,7 +39778,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z } } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -40592,9 +40669,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CON #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + } ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { if (IS_CONST == IS_UNUSED) { @@ -40630,7 +40707,7 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R if (IS_CV == IS_CONST || (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - do { + do { if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { @@ -40678,9 +40755,9 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -40847,9 +40924,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HAN Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -42200,7 +42277,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND } } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -42373,9 +42450,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S if (IS_CONST == IS_CONST && EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else { - zend_object *orig_obj = obj; + zend_object *orig_obj = obj; if (IS_CONST == IS_CONST) { function_name = RT_CONSTANT(opline, opline->op2); @@ -43109,7 +43186,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE } } else if (IS_CV == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { @@ -43182,9 +43259,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_GLOBAL_SPEC_C Bucket *p = (Bucket*)((char*)EG(symbol_table).arData + idx); if (EXPECTED(p->key == varname) || - (EXPECTED(p->h == ZSTR_H(varname)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, varname)))) { + (EXPECTED(p->h == ZSTR_H(varname)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, varname)))) { value = (zval*)p; /* value = &p->val; */ goto check_indirect; @@ -43516,7 +43593,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER( } } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -44381,9 +44458,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + } ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { @@ -44419,7 +44496,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN if (IS_CV == IS_CONST || (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - do { + do { if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { @@ -44467,9 +44544,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -44631,9 +44708,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HA Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -45944,7 +46021,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN } } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -46117,9 +46194,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else { - zend_object *orig_obj = obj; + zend_object *orig_obj = obj; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); @@ -46670,7 +46747,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMPVAR_HANDLER(Z } } else if (IS_CV == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { @@ -47209,9 +47286,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNU #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + } ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { if (IS_UNUSED == IS_UNUSED) { @@ -48469,7 +48546,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z } } else if (IS_CV == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { @@ -48813,7 +48890,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND } } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); @@ -49704,9 +49781,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_ #endif if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { - if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + } ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } else { if (IS_CV == IS_UNUSED) { @@ -49742,7 +49819,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER if (IS_CV == IS_CONST || (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - do { + do { if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { @@ -49790,9 +49867,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -49954,9 +50031,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLE Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(p->key == name) || - (EXPECTED(p->h == ZSTR_H(name)) && - EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, name)))) { + (EXPECTED(p->h == ZSTR_H(name)) && + EXPECTED(p->key != NULL) && + EXPECTED(zend_string_equal_content(p->key, name)))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -51340,7 +51417,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER } } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { - size_t len = ZSTR_LEN(op1_str); + size_t len = ZSTR_LEN(op1_str); str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); @@ -51513,9 +51590,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA if (IS_CV == IS_CONST && EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else { - zend_object *orig_obj = obj; + zend_object *orig_obj = obj; if (IS_CV == IS_CONST) { function_name = EX_VAR(opline->op2.var); @@ -52063,7 +52140,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_ } } else if (IS_CV == IS_TMP_VAR) { ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); } else { @@ -54391,6 +54468,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_INIT_DYNAMIC_CALL_SPEC_CV_LABEL, (void*)&&ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_LABEL, (void*)&&ZEND_DO_ICALL_SPEC_RETVAL_USED_LABEL, + (void*)&&ZEND_DO_ICALL_SPEC_OBSERVER_LABEL, + (void*)&&ZEND_DO_ICALL_SPEC_OBSERVER_LABEL, (void*)&&ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_LABEL, (void*)&&ZEND_DO_UCALL_SPEC_RETVAL_USED_LABEL, (void*)&&ZEND_DO_UCALL_SPEC_OBSERVER_LABEL, @@ -55891,6 +55970,10 @@ ZEND_API void execute_ex(zend_execute_data *ex) VM_TRACE(ZEND_DO_ICALL_SPEC_RETVAL_USED) ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_DO_ICALL_SPEC_OBSERVER): + VM_TRACE(ZEND_DO_ICALL_SPEC_OBSERVER) + ZEND_DO_ICALL_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_DO_UCALL_SPEC_RETVAL_UNUSED): VM_TRACE(ZEND_DO_UCALL_SPEC_RETVAL_UNUSED) ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -62442,6 +62525,8 @@ void zend_vm_init(void) ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HANDLER, ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER, ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER, + ZEND_DO_ICALL_SPEC_OBSERVER_HANDLER, + ZEND_DO_ICALL_SPEC_OBSERVER_HANDLER, ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_HANDLER, ZEND_DO_UCALL_SPEC_RETVAL_USED_HANDLER, ZEND_DO_UCALL_SPEC_OBSERVER_HANDLER, @@ -63749,7 +63834,7 @@ void zend_vm_init(void) 1255, 1256 | SPEC_RULE_OP1, 1261 | SPEC_RULE_OP1, - 3448, + 3450, 1266 | SPEC_RULE_OP1, 1271 | SPEC_RULE_OP1, 1276 | SPEC_RULE_OP2, @@ -63833,133 +63918,133 @@ void zend_vm_init(void) 2180, 2181, 2182 | SPEC_RULE_OP2, - 2187 | SPEC_RULE_RETVAL, - 2189 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER, - 2193 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER, - 2197 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2197 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2222 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2222 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2247 | SPEC_RULE_OP1, - 2252, - 2253 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2278, - 2279 | SPEC_RULE_OP1, - 2284, - 2285, + 2187 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER, + 2191 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER, + 2195 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER, + 2199 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2199 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2224 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2224 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2249 | SPEC_RULE_OP1, + 2254, + 2255 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2280, + 2281 | SPEC_RULE_OP1, 2286, 2287, 2288, 2289, 2290, - 2291 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2316, - 2317, + 2291, + 2292, + 2293 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2318, - 2319 | SPEC_RULE_OP1, - 2324, - 2325 | SPEC_RULE_ISSET, - 2327 | SPEC_RULE_OP2, - 2332, - 2333 | SPEC_RULE_OP1, - 2338 | SPEC_RULE_OBSERVER, - 2340, - 2341 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2366 | SPEC_RULE_OP1 | SPEC_RULE_OBSERVER, - 2376, - 2377, + 2319, + 2320, + 2321 | SPEC_RULE_OP1, + 2326, + 2327 | SPEC_RULE_ISSET, + 2329 | SPEC_RULE_OP2, + 2334, + 2335 | SPEC_RULE_OP1, + 2340 | SPEC_RULE_OBSERVER, + 2342, + 2343 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2368 | SPEC_RULE_OP1 | SPEC_RULE_OBSERVER, 2378, 2379, - 2380 | SPEC_RULE_OP1, - 2385, - 2386, - 2387 | SPEC_RULE_OP1, - 2392 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2417, - 2418 | SPEC_RULE_OP1, - 2423, - 2424, + 2380, + 2381, + 2382 | SPEC_RULE_OP1, + 2387, + 2388, + 2389 | SPEC_RULE_OP1, + 2394 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2419, + 2420 | SPEC_RULE_OP1, 2425, 2426, 2427, 2428, 2429, 2430, - 2431 | SPEC_RULE_OP1, - 2436, - 2437, + 2431, + 2432, + 2433 | SPEC_RULE_OP1, 2438, - 2439 | SPEC_RULE_OP2, - 2444, - 2445 | SPEC_RULE_OP1, - 2450 | SPEC_RULE_OP1, - 2455 | SPEC_RULE_OP1, - 2460 | SPEC_RULE_OP1, - 2465 | SPEC_RULE_OP1, - 2470, - 2471 | SPEC_RULE_OP1, - 2476 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2501 | SPEC_RULE_OP1, - 2506 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2531 | SPEC_RULE_OP1, - 2536 | SPEC_RULE_OP1, - 2541, - 2542, + 2439, + 2440, + 2441 | SPEC_RULE_OP2, + 2446, + 2447 | SPEC_RULE_OP1, + 2452 | SPEC_RULE_OP1, + 2457 | SPEC_RULE_OP1, + 2462 | SPEC_RULE_OP1, + 2467 | SPEC_RULE_OP1, + 2472, + 2473 | SPEC_RULE_OP1, + 2478 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2503 | SPEC_RULE_OP1, + 2508 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2533 | SPEC_RULE_OP1, + 2538 | SPEC_RULE_OP1, 2543, 2544, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, - 3448, + 2545, + 2546, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, + 3450, }; #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) zend_opcode_handler_funcs = labels; @@ -64132,7 +64217,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2547 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2549 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -64140,7 +64225,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2572 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2574 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -64148,7 +64233,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2597 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2599 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -64159,17 +64244,17 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2622 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2624 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } else if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2647 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2649 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2672 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2674 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } break; case ZEND_MUL: @@ -64180,17 +64265,17 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2697 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2699 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2722 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2724 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2747 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2749 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_IDENTICAL: @@ -64201,14 +64286,14 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2772 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2774 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2847 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2849 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) { - spec = 3072 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 3074 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_NOT_IDENTICAL: @@ -64219,14 +64304,14 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2922 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2924 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2997 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2999 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) { - spec = 3077 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 3079 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_EQUAL: @@ -64237,12 +64322,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2772 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2774 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2847 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2849 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_NOT_EQUAL: @@ -64253,12 +64338,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2922 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2924 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2997 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2999 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_SMALLER: @@ -64266,12 +64351,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3082 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3084 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3157 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3159 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } break; case ZEND_IS_SMALLER_OR_EQUAL: @@ -64279,74 +64364,74 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3232 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3234 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3307 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3309 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } break; case ZEND_QM_ASSIGN: if (op1_info == MAY_BE_LONG) { - spec = 3394 | SPEC_RULE_OP1; + spec = 3396 | SPEC_RULE_OP1; } else if (op1_info == MAY_BE_DOUBLE) { - spec = 3399 | SPEC_RULE_OP1; + spec = 3401 | SPEC_RULE_OP1; } else if ((op->op1_type == IS_CONST) ? !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1)) : (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE))))) { - spec = 3404 | SPEC_RULE_OP1; + spec = 3406 | SPEC_RULE_OP1; } break; case ZEND_PRE_INC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3382 | SPEC_RULE_RETVAL; - } else if (op1_info == MAY_BE_LONG) { spec = 3384 | SPEC_RULE_RETVAL; + } else if (op1_info == MAY_BE_LONG) { + spec = 3386 | SPEC_RULE_RETVAL; } break; case ZEND_PRE_DEC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3386 | SPEC_RULE_RETVAL; - } else if (op1_info == MAY_BE_LONG) { spec = 3388 | SPEC_RULE_RETVAL; + } else if (op1_info == MAY_BE_LONG) { + spec = 3390 | SPEC_RULE_RETVAL; } break; case ZEND_POST_INC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3390; + spec = 3392; } else if (op1_info == MAY_BE_LONG) { - spec = 3391; + spec = 3393; } break; case ZEND_POST_DEC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3392; + spec = 3394; } else if (op1_info == MAY_BE_LONG) { - spec = 3393; + spec = 3395; } break; case ZEND_JMP: if (OP_JMP_ADDR(op, op->op1) > op) { - spec = 2546; + spec = 2548; } break; case ZEND_RECV: if (op->op2.num == MAY_BE_ANY) { - spec = 2545; + spec = 2547; } break; case ZEND_SEND_VAL: if (op->op1_type == IS_CONST && op->op2_type == IS_UNUSED && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) { - spec = 3444; + spec = 3446; } break; case ZEND_SEND_VAR_EX: if (op->op2_type == IS_UNUSED && op->op2.num <= MAX_ARG_FLAG_NUM && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { - spec = 3439 | SPEC_RULE_OP1; + spec = 3441 | SPEC_RULE_OP1; } break; case ZEND_FE_FETCH_R: if (op->op2_type == IS_CV && (op1_info & (MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY) { - spec = 3446 | SPEC_RULE_RETVAL; + spec = 3448 | SPEC_RULE_RETVAL; } break; case ZEND_FETCH_DIM_R: @@ -64354,17 +64439,17 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3409 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 3411 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } break; case ZEND_SEND_VAL_EX: if (op->op2_type == IS_UNUSED && op->op2.num <= MAX_ARG_FLAG_NUM && op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) { - spec = 3445; + spec = 3447; } break; case ZEND_SEND_VAR: if (op->op2_type == IS_UNUSED && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { - spec = 3434 | SPEC_RULE_OP1; + spec = 3436 | SPEC_RULE_OP1; } break; case ZEND_BW_OR: diff --git a/Zend/zend_vm_handlers.h b/Zend/zend_vm_handlers.h index 5f651ded1f35f..d07c63d89f4f7 100644 --- a/Zend/zend_vm_handlers.h +++ b/Zend/zend_vm_handlers.h @@ -1105,744 +1105,746 @@ _(2186, ZEND_INIT_DYNAMIC_CALL_SPEC_CV) \ _(2187, ZEND_DO_ICALL_SPEC_RETVAL_UNUSED) \ _(2188, ZEND_DO_ICALL_SPEC_RETVAL_USED) \ - _(2189, ZEND_DO_UCALL_SPEC_RETVAL_UNUSED) \ - _(2190, ZEND_DO_UCALL_SPEC_RETVAL_USED) \ - _(2191, ZEND_DO_UCALL_SPEC_OBSERVER) \ - _(2192, ZEND_DO_UCALL_SPEC_OBSERVER) \ - _(2193, ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED) \ - _(2194, ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED) \ - _(2195, ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER) \ - _(2196, ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER) \ - _(2207, ZEND_PRE_INC_OBJ_SPEC_VAR_CONST) \ - _(2208, ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR) \ - _(2209, ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR) \ - _(2211, ZEND_PRE_INC_OBJ_SPEC_VAR_CV) \ - _(2212, ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST) \ - _(2213, ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR) \ - _(2214, ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR) \ - _(2216, ZEND_PRE_INC_OBJ_SPEC_UNUSED_CV) \ - _(2217, ZEND_PRE_INC_OBJ_SPEC_CV_CONST) \ - _(2218, ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR) \ - _(2219, ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR) \ - _(2221, ZEND_PRE_INC_OBJ_SPEC_CV_CV) \ - _(2232, ZEND_POST_INC_OBJ_SPEC_VAR_CONST) \ - _(2233, ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR) \ - _(2234, ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR) \ - _(2236, ZEND_POST_INC_OBJ_SPEC_VAR_CV) \ - _(2237, ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST) \ - _(2238, ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR) \ - _(2239, ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR) \ - _(2241, ZEND_POST_INC_OBJ_SPEC_UNUSED_CV) \ - _(2242, ZEND_POST_INC_OBJ_SPEC_CV_CONST) \ - _(2243, ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR) \ - _(2244, ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR) \ - _(2246, ZEND_POST_INC_OBJ_SPEC_CV_CV) \ - _(2247, ZEND_ECHO_SPEC_CONST) \ - _(2248, ZEND_ECHO_SPEC_TMPVAR) \ - _(2249, ZEND_ECHO_SPEC_TMPVAR) \ - _(2251, ZEND_ECHO_SPEC_CV) \ - _(2258, ZEND_INSTANCEOF_SPEC_TMPVAR_CONST) \ - _(2260, ZEND_INSTANCEOF_SPEC_TMPVAR_VAR) \ - _(2261, ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED) \ - _(2263, ZEND_INSTANCEOF_SPEC_TMPVAR_CONST) \ - _(2265, ZEND_INSTANCEOF_SPEC_TMPVAR_VAR) \ - _(2266, ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED) \ - _(2273, ZEND_INSTANCEOF_SPEC_CV_CONST) \ - _(2275, ZEND_INSTANCEOF_SPEC_CV_VAR) \ - _(2276, ZEND_INSTANCEOF_SPEC_CV_UNUSED) \ - _(2278, ZEND_GENERATOR_CREATE_SPEC) \ - _(2281, ZEND_MAKE_REF_SPEC_VAR_UNUSED) \ - _(2283, ZEND_MAKE_REF_SPEC_CV_UNUSED) \ - _(2284, ZEND_DECLARE_FUNCTION_SPEC) \ - _(2285, ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST) \ - _(2286, ZEND_DECLARE_CONST_SPEC_CONST_CONST) \ - _(2287, ZEND_DECLARE_CLASS_SPEC_CONST) \ - _(2288, ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST) \ - _(2289, ZEND_DECLARE_ANON_CLASS_SPEC) \ - _(2290, ZEND_ADD_ARRAY_UNPACK_SPEC) \ - _(2291, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST) \ - _(2292, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR) \ - _(2293, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR) \ - _(2295, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV) \ - _(2296, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST) \ - _(2297, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR) \ - _(2298, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR) \ - _(2300, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV) \ - _(2301, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST) \ - _(2302, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR) \ - _(2303, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR) \ - _(2305, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV) \ - _(2306, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST) \ - _(2307, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR) \ - _(2308, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR) \ - _(2310, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV) \ - _(2311, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST) \ - _(2312, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR) \ - _(2313, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR) \ - _(2315, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV) \ - _(2316, ZEND_HANDLE_EXCEPTION_SPEC) \ - _(2317, ZEND_USER_OPCODE_SPEC) \ - _(2318, ZEND_ASSERT_CHECK_SPEC) \ - _(2319, ZEND_JMP_SET_SPEC_CONST) \ - _(2320, ZEND_JMP_SET_SPEC_TMP) \ - _(2321, ZEND_JMP_SET_SPEC_VAR) \ - _(2323, ZEND_JMP_SET_SPEC_CV) \ - _(2324, ZEND_UNSET_CV_SPEC_CV_UNUSED) \ - _(2325, ZEND_ISSET_ISEMPTY_CV_SPEC_CV_UNUSED_SET) \ - _(2326, ZEND_ISSET_ISEMPTY_CV_SPEC_CV_UNUSED_EMPTY) \ - _(2327, ZEND_FETCH_LIST_W_SPEC_VAR_CONST) \ - _(2328, ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR) \ - _(2329, ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR) \ - _(2331, ZEND_FETCH_LIST_W_SPEC_VAR_CV) \ - _(2332, ZEND_SEPARATE_SPEC_VAR_UNUSED) \ - _(2334, ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR) \ - _(2335, ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR) \ - _(2336, ZEND_FETCH_CLASS_NAME_SPEC_UNUSED) \ - _(2337, ZEND_FETCH_CLASS_NAME_SPEC_CV) \ - _(2338, ZEND_CALL_TRAMPOLINE_SPEC) \ - _(2339, ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER) \ - _(2340, ZEND_DISCARD_EXCEPTION_SPEC) \ - _(2341, ZEND_YIELD_SPEC_CONST_CONST) \ - _(2342, ZEND_YIELD_SPEC_CONST_TMPVAR) \ - _(2343, ZEND_YIELD_SPEC_CONST_TMPVAR) \ - _(2344, ZEND_YIELD_SPEC_CONST_UNUSED) \ - _(2345, ZEND_YIELD_SPEC_CONST_CV) \ - _(2346, ZEND_YIELD_SPEC_TMP_CONST) \ - _(2347, ZEND_YIELD_SPEC_TMP_TMPVAR) \ - _(2348, ZEND_YIELD_SPEC_TMP_TMPVAR) \ - _(2349, ZEND_YIELD_SPEC_TMP_UNUSED) \ - _(2350, ZEND_YIELD_SPEC_TMP_CV) \ - _(2351, ZEND_YIELD_SPEC_VAR_CONST) \ - _(2352, ZEND_YIELD_SPEC_VAR_TMPVAR) \ - _(2353, ZEND_YIELD_SPEC_VAR_TMPVAR) \ - _(2354, ZEND_YIELD_SPEC_VAR_UNUSED) \ - _(2355, ZEND_YIELD_SPEC_VAR_CV) \ - _(2356, ZEND_YIELD_SPEC_UNUSED_CONST) \ - _(2357, ZEND_YIELD_SPEC_UNUSED_TMPVAR) \ - _(2358, ZEND_YIELD_SPEC_UNUSED_TMPVAR) \ - _(2359, ZEND_YIELD_SPEC_UNUSED_UNUSED) \ - _(2360, ZEND_YIELD_SPEC_UNUSED_CV) \ - _(2361, ZEND_YIELD_SPEC_CV_CONST) \ - _(2362, ZEND_YIELD_SPEC_CV_TMPVAR) \ - _(2363, ZEND_YIELD_SPEC_CV_TMPVAR) \ - _(2364, ZEND_YIELD_SPEC_CV_UNUSED) \ - _(2365, ZEND_YIELD_SPEC_CV_CV) \ - _(2366, ZEND_GENERATOR_RETURN_SPEC_CONST) \ - _(2367, ZEND_GENERATOR_RETURN_SPEC_OBSERVER) \ - _(2368, ZEND_GENERATOR_RETURN_SPEC_TMP) \ + _(2189, ZEND_DO_ICALL_SPEC_OBSERVER) \ + _(2190, ZEND_DO_ICALL_SPEC_OBSERVER) \ + _(2191, ZEND_DO_UCALL_SPEC_RETVAL_UNUSED) \ + _(2192, ZEND_DO_UCALL_SPEC_RETVAL_USED) \ + _(2193, ZEND_DO_UCALL_SPEC_OBSERVER) \ + _(2194, ZEND_DO_UCALL_SPEC_OBSERVER) \ + _(2195, ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED) \ + _(2196, ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED) \ + _(2197, ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER) \ + _(2198, ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER) \ + _(2209, ZEND_PRE_INC_OBJ_SPEC_VAR_CONST) \ + _(2210, ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR) \ + _(2211, ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR) \ + _(2213, ZEND_PRE_INC_OBJ_SPEC_VAR_CV) \ + _(2214, ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST) \ + _(2215, ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR) \ + _(2216, ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR) \ + _(2218, ZEND_PRE_INC_OBJ_SPEC_UNUSED_CV) \ + _(2219, ZEND_PRE_INC_OBJ_SPEC_CV_CONST) \ + _(2220, ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR) \ + _(2221, ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR) \ + _(2223, ZEND_PRE_INC_OBJ_SPEC_CV_CV) \ + _(2234, ZEND_POST_INC_OBJ_SPEC_VAR_CONST) \ + _(2235, ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR) \ + _(2236, ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR) \ + _(2238, ZEND_POST_INC_OBJ_SPEC_VAR_CV) \ + _(2239, ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST) \ + _(2240, ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR) \ + _(2241, ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR) \ + _(2243, ZEND_POST_INC_OBJ_SPEC_UNUSED_CV) \ + _(2244, ZEND_POST_INC_OBJ_SPEC_CV_CONST) \ + _(2245, ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR) \ + _(2246, ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR) \ + _(2248, ZEND_POST_INC_OBJ_SPEC_CV_CV) \ + _(2249, ZEND_ECHO_SPEC_CONST) \ + _(2250, ZEND_ECHO_SPEC_TMPVAR) \ + _(2251, ZEND_ECHO_SPEC_TMPVAR) \ + _(2253, ZEND_ECHO_SPEC_CV) \ + _(2260, ZEND_INSTANCEOF_SPEC_TMPVAR_CONST) \ + _(2262, ZEND_INSTANCEOF_SPEC_TMPVAR_VAR) \ + _(2263, ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED) \ + _(2265, ZEND_INSTANCEOF_SPEC_TMPVAR_CONST) \ + _(2267, ZEND_INSTANCEOF_SPEC_TMPVAR_VAR) \ + _(2268, ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED) \ + _(2275, ZEND_INSTANCEOF_SPEC_CV_CONST) \ + _(2277, ZEND_INSTANCEOF_SPEC_CV_VAR) \ + _(2278, ZEND_INSTANCEOF_SPEC_CV_UNUSED) \ + _(2280, ZEND_GENERATOR_CREATE_SPEC) \ + _(2283, ZEND_MAKE_REF_SPEC_VAR_UNUSED) \ + _(2285, ZEND_MAKE_REF_SPEC_CV_UNUSED) \ + _(2286, ZEND_DECLARE_FUNCTION_SPEC) \ + _(2287, ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST) \ + _(2288, ZEND_DECLARE_CONST_SPEC_CONST_CONST) \ + _(2289, ZEND_DECLARE_CLASS_SPEC_CONST) \ + _(2290, ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST) \ + _(2291, ZEND_DECLARE_ANON_CLASS_SPEC) \ + _(2292, ZEND_ADD_ARRAY_UNPACK_SPEC) \ + _(2293, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST) \ + _(2294, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR) \ + _(2295, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR) \ + _(2297, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV) \ + _(2298, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST) \ + _(2299, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR) \ + _(2300, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR) \ + _(2302, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV) \ + _(2303, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST) \ + _(2304, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR) \ + _(2305, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR) \ + _(2307, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV) \ + _(2308, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST) \ + _(2309, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR) \ + _(2310, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR) \ + _(2312, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV) \ + _(2313, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST) \ + _(2314, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR) \ + _(2315, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR) \ + _(2317, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV) \ + _(2318, ZEND_HANDLE_EXCEPTION_SPEC) \ + _(2319, ZEND_USER_OPCODE_SPEC) \ + _(2320, ZEND_ASSERT_CHECK_SPEC) \ + _(2321, ZEND_JMP_SET_SPEC_CONST) \ + _(2322, ZEND_JMP_SET_SPEC_TMP) \ + _(2323, ZEND_JMP_SET_SPEC_VAR) \ + _(2325, ZEND_JMP_SET_SPEC_CV) \ + _(2326, ZEND_UNSET_CV_SPEC_CV_UNUSED) \ + _(2327, ZEND_ISSET_ISEMPTY_CV_SPEC_CV_UNUSED_SET) \ + _(2328, ZEND_ISSET_ISEMPTY_CV_SPEC_CV_UNUSED_EMPTY) \ + _(2329, ZEND_FETCH_LIST_W_SPEC_VAR_CONST) \ + _(2330, ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR) \ + _(2331, ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR) \ + _(2333, ZEND_FETCH_LIST_W_SPEC_VAR_CV) \ + _(2334, ZEND_SEPARATE_SPEC_VAR_UNUSED) \ + _(2336, ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR) \ + _(2337, ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR) \ + _(2338, ZEND_FETCH_CLASS_NAME_SPEC_UNUSED) \ + _(2339, ZEND_FETCH_CLASS_NAME_SPEC_CV) \ + _(2340, ZEND_CALL_TRAMPOLINE_SPEC) \ + _(2341, ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER) \ + _(2342, ZEND_DISCARD_EXCEPTION_SPEC) \ + _(2343, ZEND_YIELD_SPEC_CONST_CONST) \ + _(2344, ZEND_YIELD_SPEC_CONST_TMPVAR) \ + _(2345, ZEND_YIELD_SPEC_CONST_TMPVAR) \ + _(2346, ZEND_YIELD_SPEC_CONST_UNUSED) \ + _(2347, ZEND_YIELD_SPEC_CONST_CV) \ + _(2348, ZEND_YIELD_SPEC_TMP_CONST) \ + _(2349, ZEND_YIELD_SPEC_TMP_TMPVAR) \ + _(2350, ZEND_YIELD_SPEC_TMP_TMPVAR) \ + _(2351, ZEND_YIELD_SPEC_TMP_UNUSED) \ + _(2352, ZEND_YIELD_SPEC_TMP_CV) \ + _(2353, ZEND_YIELD_SPEC_VAR_CONST) \ + _(2354, ZEND_YIELD_SPEC_VAR_TMPVAR) \ + _(2355, ZEND_YIELD_SPEC_VAR_TMPVAR) \ + _(2356, ZEND_YIELD_SPEC_VAR_UNUSED) \ + _(2357, ZEND_YIELD_SPEC_VAR_CV) \ + _(2358, ZEND_YIELD_SPEC_UNUSED_CONST) \ + _(2359, ZEND_YIELD_SPEC_UNUSED_TMPVAR) \ + _(2360, ZEND_YIELD_SPEC_UNUSED_TMPVAR) \ + _(2361, ZEND_YIELD_SPEC_UNUSED_UNUSED) \ + _(2362, ZEND_YIELD_SPEC_UNUSED_CV) \ + _(2363, ZEND_YIELD_SPEC_CV_CONST) \ + _(2364, ZEND_YIELD_SPEC_CV_TMPVAR) \ + _(2365, ZEND_YIELD_SPEC_CV_TMPVAR) \ + _(2366, ZEND_YIELD_SPEC_CV_UNUSED) \ + _(2367, ZEND_YIELD_SPEC_CV_CV) \ + _(2368, ZEND_GENERATOR_RETURN_SPEC_CONST) \ _(2369, ZEND_GENERATOR_RETURN_SPEC_OBSERVER) \ - _(2370, ZEND_GENERATOR_RETURN_SPEC_VAR) \ + _(2370, ZEND_GENERATOR_RETURN_SPEC_TMP) \ _(2371, ZEND_GENERATOR_RETURN_SPEC_OBSERVER) \ - _(2374, ZEND_GENERATOR_RETURN_SPEC_CV) \ - _(2375, ZEND_GENERATOR_RETURN_SPEC_OBSERVER) \ - _(2376, ZEND_FAST_CALL_SPEC) \ - _(2377, ZEND_FAST_RET_SPEC) \ - _(2378, ZEND_RECV_VARIADIC_SPEC_UNUSED) \ - _(2379, ZEND_SEND_UNPACK_SPEC) \ - _(2380, ZEND_YIELD_FROM_SPEC_CONST) \ - _(2381, ZEND_YIELD_FROM_SPEC_TMPVAR) \ - _(2382, ZEND_YIELD_FROM_SPEC_TMPVAR) \ - _(2384, ZEND_YIELD_FROM_SPEC_CV) \ - _(2385, ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED) \ - _(2386, ZEND_BIND_GLOBAL_SPEC_CV_CONST) \ - _(2387, ZEND_COALESCE_SPEC_CONST) \ - _(2388, ZEND_COALESCE_SPEC_TMP) \ - _(2389, ZEND_COALESCE_SPEC_VAR) \ - _(2391, ZEND_COALESCE_SPEC_CV) \ - _(2392, ZEND_SPACESHIP_SPEC_CONST_CONST) \ - _(2393, ZEND_SPACESHIP_SPEC_CONST_TMPVAR) \ - _(2394, ZEND_SPACESHIP_SPEC_CONST_TMPVAR) \ - _(2396, ZEND_SPACESHIP_SPEC_CONST_CV) \ - _(2397, ZEND_SPACESHIP_SPEC_TMPVAR_CONST) \ - _(2398, ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR) \ - _(2399, ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR) \ - _(2401, ZEND_SPACESHIP_SPEC_TMPVAR_CV) \ - _(2402, ZEND_SPACESHIP_SPEC_TMPVAR_CONST) \ - _(2403, ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR) \ - _(2404, ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR) \ - _(2406, ZEND_SPACESHIP_SPEC_TMPVAR_CV) \ - _(2412, ZEND_SPACESHIP_SPEC_CV_CONST) \ - _(2413, ZEND_SPACESHIP_SPEC_CV_TMPVAR) \ - _(2414, ZEND_SPACESHIP_SPEC_CV_TMPVAR) \ - _(2416, ZEND_SPACESHIP_SPEC_CV_CV) \ - _(2417, ZEND_FUNC_NUM_ARGS_SPEC_UNUSED_UNUSED) \ - _(2418, ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSED) \ - _(2421, ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUSED) \ - _(2423, ZEND_FETCH_STATIC_PROP_R_SPEC) \ - _(2424, ZEND_FETCH_STATIC_PROP_W_SPEC) \ - _(2425, ZEND_FETCH_STATIC_PROP_RW_SPEC) \ - _(2426, ZEND_FETCH_STATIC_PROP_IS_SPEC) \ - _(2427, ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC) \ - _(2428, ZEND_FETCH_STATIC_PROP_UNSET_SPEC) \ - _(2429, ZEND_UNSET_STATIC_PROP_SPEC) \ - _(2430, ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC) \ - _(2431, ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_CONST) \ - _(2433, ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST) \ - _(2434, ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_CONST) \ - _(2436, ZEND_BIND_LEXICAL_SPEC_TMP_CV) \ - _(2437, ZEND_BIND_STATIC_SPEC_CV_UNUSED) \ - _(2438, ZEND_FETCH_THIS_SPEC_UNUSED_UNUSED) \ - _(2439, ZEND_SEND_FUNC_ARG_SPEC_VAR_CONST) \ - _(2442, ZEND_SEND_FUNC_ARG_SPEC_VAR_UNUSED) \ - _(2444, ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED_UNUSED) \ - _(2445, ZEND_SWITCH_LONG_SPEC_CONST_CONST) \ - _(2446, ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONST) \ - _(2447, ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONST) \ + _(2372, ZEND_GENERATOR_RETURN_SPEC_VAR) \ + _(2373, ZEND_GENERATOR_RETURN_SPEC_OBSERVER) \ + _(2376, ZEND_GENERATOR_RETURN_SPEC_CV) \ + _(2377, ZEND_GENERATOR_RETURN_SPEC_OBSERVER) \ + _(2378, ZEND_FAST_CALL_SPEC) \ + _(2379, ZEND_FAST_RET_SPEC) \ + _(2380, ZEND_RECV_VARIADIC_SPEC_UNUSED) \ + _(2381, ZEND_SEND_UNPACK_SPEC) \ + _(2382, ZEND_YIELD_FROM_SPEC_CONST) \ + _(2383, ZEND_YIELD_FROM_SPEC_TMPVAR) \ + _(2384, ZEND_YIELD_FROM_SPEC_TMPVAR) \ + _(2386, ZEND_YIELD_FROM_SPEC_CV) \ + _(2387, ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED) \ + _(2388, ZEND_BIND_GLOBAL_SPEC_CV_CONST) \ + _(2389, ZEND_COALESCE_SPEC_CONST) \ + _(2390, ZEND_COALESCE_SPEC_TMP) \ + _(2391, ZEND_COALESCE_SPEC_VAR) \ + _(2393, ZEND_COALESCE_SPEC_CV) \ + _(2394, ZEND_SPACESHIP_SPEC_CONST_CONST) \ + _(2395, ZEND_SPACESHIP_SPEC_CONST_TMPVAR) \ + _(2396, ZEND_SPACESHIP_SPEC_CONST_TMPVAR) \ + _(2398, ZEND_SPACESHIP_SPEC_CONST_CV) \ + _(2399, ZEND_SPACESHIP_SPEC_TMPVAR_CONST) \ + _(2400, ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR) \ + _(2401, ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR) \ + _(2403, ZEND_SPACESHIP_SPEC_TMPVAR_CV) \ + _(2404, ZEND_SPACESHIP_SPEC_TMPVAR_CONST) \ + _(2405, ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR) \ + _(2406, ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR) \ + _(2408, ZEND_SPACESHIP_SPEC_TMPVAR_CV) \ + _(2414, ZEND_SPACESHIP_SPEC_CV_CONST) \ + _(2415, ZEND_SPACESHIP_SPEC_CV_TMPVAR) \ + _(2416, ZEND_SPACESHIP_SPEC_CV_TMPVAR) \ + _(2418, ZEND_SPACESHIP_SPEC_CV_CV) \ + _(2419, ZEND_FUNC_NUM_ARGS_SPEC_UNUSED_UNUSED) \ + _(2420, ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSED) \ + _(2423, ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUSED) \ + _(2425, ZEND_FETCH_STATIC_PROP_R_SPEC) \ + _(2426, ZEND_FETCH_STATIC_PROP_W_SPEC) \ + _(2427, ZEND_FETCH_STATIC_PROP_RW_SPEC) \ + _(2428, ZEND_FETCH_STATIC_PROP_IS_SPEC) \ + _(2429, ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC) \ + _(2430, ZEND_FETCH_STATIC_PROP_UNSET_SPEC) \ + _(2431, ZEND_UNSET_STATIC_PROP_SPEC) \ + _(2432, ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC) \ + _(2433, ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_CONST) \ + _(2435, ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST) \ + _(2436, ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_CONST) \ + _(2438, ZEND_BIND_LEXICAL_SPEC_TMP_CV) \ + _(2439, ZEND_BIND_STATIC_SPEC_CV_UNUSED) \ + _(2440, ZEND_FETCH_THIS_SPEC_UNUSED_UNUSED) \ + _(2441, ZEND_SEND_FUNC_ARG_SPEC_VAR_CONST) \ + _(2444, ZEND_SEND_FUNC_ARG_SPEC_VAR_UNUSED) \ + _(2446, ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED_UNUSED) \ + _(2447, ZEND_SWITCH_LONG_SPEC_CONST_CONST) \ + _(2448, ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONST) \ _(2449, ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONST) \ - _(2450, ZEND_SWITCH_STRING_SPEC_CONST_CONST) \ - _(2451, ZEND_SWITCH_STRING_SPEC_TMPVARCV_CONST) \ - _(2452, ZEND_SWITCH_STRING_SPEC_TMPVARCV_CONST) \ + _(2451, ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONST) \ + _(2452, ZEND_SWITCH_STRING_SPEC_CONST_CONST) \ + _(2453, ZEND_SWITCH_STRING_SPEC_TMPVARCV_CONST) \ _(2454, ZEND_SWITCH_STRING_SPEC_TMPVARCV_CONST) \ - _(2455, ZEND_IN_ARRAY_SPEC_CONST_CONST) \ - _(2456, ZEND_IN_ARRAY_SPEC_TMP_CONST) \ - _(2457, ZEND_IN_ARRAY_SPEC_VAR_CONST) \ - _(2459, ZEND_IN_ARRAY_SPEC_CV_CONST) \ - _(2460, ZEND_COUNT_SPEC_CONST_UNUSED) \ - _(2461, ZEND_COUNT_SPEC_TMPVAR_UNUSED) \ - _(2462, ZEND_COUNT_SPEC_TMPVAR_UNUSED) \ - _(2464, ZEND_COUNT_SPEC_CV_UNUSED) \ - _(2465, ZEND_GET_CLASS_SPEC_CONST_UNUSED) \ - _(2466, ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED) \ - _(2467, ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED) \ - _(2468, ZEND_GET_CLASS_SPEC_UNUSED_UNUSED) \ - _(2469, ZEND_GET_CLASS_SPEC_CV_UNUSED) \ - _(2470, ZEND_GET_CALLED_CLASS_SPEC_UNUSED_UNUSED) \ - _(2471, ZEND_GET_TYPE_SPEC_CONST_UNUSED) \ - _(2472, ZEND_GET_TYPE_SPEC_TMP_UNUSED) \ - _(2473, ZEND_GET_TYPE_SPEC_VAR_UNUSED) \ - _(2475, ZEND_GET_TYPE_SPEC_CV_UNUSED) \ - _(2476, ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CONST) \ - _(2477, ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_TMPVAR) \ - _(2478, ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_TMPVAR) \ - _(2480, ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CV) \ - _(2481, ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CONST) \ - _(2482, ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR) \ - _(2483, ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR) \ - _(2485, ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CV) \ - _(2486, ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CONST) \ - _(2487, ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR) \ - _(2488, ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR) \ - _(2490, ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CV) \ - _(2496, ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CONST) \ - _(2497, ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR) \ - _(2498, ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR) \ - _(2500, ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CV) \ - _(2501, ZEND_MATCH_SPEC_CONST_CONST) \ - _(2502, ZEND_MATCH_SPEC_TMPVARCV_CONST) \ - _(2503, ZEND_MATCH_SPEC_TMPVARCV_CONST) \ + _(2456, ZEND_SWITCH_STRING_SPEC_TMPVARCV_CONST) \ + _(2457, ZEND_IN_ARRAY_SPEC_CONST_CONST) \ + _(2458, ZEND_IN_ARRAY_SPEC_TMP_CONST) \ + _(2459, ZEND_IN_ARRAY_SPEC_VAR_CONST) \ + _(2461, ZEND_IN_ARRAY_SPEC_CV_CONST) \ + _(2462, ZEND_COUNT_SPEC_CONST_UNUSED) \ + _(2463, ZEND_COUNT_SPEC_TMPVAR_UNUSED) \ + _(2464, ZEND_COUNT_SPEC_TMPVAR_UNUSED) \ + _(2466, ZEND_COUNT_SPEC_CV_UNUSED) \ + _(2467, ZEND_GET_CLASS_SPEC_CONST_UNUSED) \ + _(2468, ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED) \ + _(2469, ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED) \ + _(2470, ZEND_GET_CLASS_SPEC_UNUSED_UNUSED) \ + _(2471, ZEND_GET_CLASS_SPEC_CV_UNUSED) \ + _(2472, ZEND_GET_CALLED_CLASS_SPEC_UNUSED_UNUSED) \ + _(2473, ZEND_GET_TYPE_SPEC_CONST_UNUSED) \ + _(2474, ZEND_GET_TYPE_SPEC_TMP_UNUSED) \ + _(2475, ZEND_GET_TYPE_SPEC_VAR_UNUSED) \ + _(2477, ZEND_GET_TYPE_SPEC_CV_UNUSED) \ + _(2478, ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CONST) \ + _(2479, ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_TMPVAR) \ + _(2480, ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_TMPVAR) \ + _(2482, ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CV) \ + _(2483, ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CONST) \ + _(2484, ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR) \ + _(2485, ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR) \ + _(2487, ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CV) \ + _(2488, ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CONST) \ + _(2489, ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR) \ + _(2490, ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR) \ + _(2492, ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CV) \ + _(2498, ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CONST) \ + _(2499, ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR) \ + _(2500, ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR) \ + _(2502, ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CV) \ + _(2503, ZEND_MATCH_SPEC_CONST_CONST) \ + _(2504, ZEND_MATCH_SPEC_TMPVARCV_CONST) \ _(2505, ZEND_MATCH_SPEC_TMPVARCV_CONST) \ - _(2511, ZEND_CASE_STRICT_SPEC_TMP_CONST) \ - _(2512, ZEND_CASE_STRICT_SPEC_TMP_TMP) \ - _(2513, ZEND_CASE_STRICT_SPEC_TMP_VAR) \ - _(2515, ZEND_CASE_STRICT_SPEC_TMP_CV) \ - _(2516, ZEND_CASE_STRICT_SPEC_VAR_CONST) \ - _(2517, ZEND_CASE_STRICT_SPEC_VAR_TMP) \ - _(2518, ZEND_CASE_STRICT_SPEC_VAR_VAR) \ - _(2520, ZEND_CASE_STRICT_SPEC_VAR_CV) \ - _(2531, ZEND_MATCH_ERROR_SPEC_CONST_UNUSED) \ - _(2532, ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED) \ - _(2533, ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED) \ + _(2507, ZEND_MATCH_SPEC_TMPVARCV_CONST) \ + _(2513, ZEND_CASE_STRICT_SPEC_TMP_CONST) \ + _(2514, ZEND_CASE_STRICT_SPEC_TMP_TMP) \ + _(2515, ZEND_CASE_STRICT_SPEC_TMP_VAR) \ + _(2517, ZEND_CASE_STRICT_SPEC_TMP_CV) \ + _(2518, ZEND_CASE_STRICT_SPEC_VAR_CONST) \ + _(2519, ZEND_CASE_STRICT_SPEC_VAR_TMP) \ + _(2520, ZEND_CASE_STRICT_SPEC_VAR_VAR) \ + _(2522, ZEND_CASE_STRICT_SPEC_VAR_CV) \ + _(2533, ZEND_MATCH_ERROR_SPEC_CONST_UNUSED) \ + _(2534, ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED) \ _(2535, ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED) \ - _(2536, ZEND_JMP_NULL_SPEC_CONST) \ - _(2537, ZEND_JMP_NULL_SPEC_TMP) \ - _(2538, ZEND_JMP_NULL_SPEC_VAR) \ - _(2540, ZEND_JMP_NULL_SPEC_CV) \ - _(2541, ZEND_CHECK_UNDEF_ARGS_SPEC_UNUSED_UNUSED) \ - _(2542, ZEND_FETCH_GLOBALS_SPEC_UNUSED_UNUSED) \ - _(2543, ZEND_VERIFY_NEVER_TYPE_SPEC_UNUSED_UNUSED) \ - _(2544, ZEND_CALLABLE_CONVERT_SPEC_UNUSED_UNUSED) \ - _(2545, ZEND_RECV_NOTYPE_SPEC) \ - _(2546, ZEND_JMP_FORWARD_SPEC) \ - _(2552, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2553, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2554, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2537, ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED) \ + _(2538, ZEND_JMP_NULL_SPEC_CONST) \ + _(2539, ZEND_JMP_NULL_SPEC_TMP) \ + _(2540, ZEND_JMP_NULL_SPEC_VAR) \ + _(2542, ZEND_JMP_NULL_SPEC_CV) \ + _(2543, ZEND_CHECK_UNDEF_ARGS_SPEC_UNUSED_UNUSED) \ + _(2544, ZEND_FETCH_GLOBALS_SPEC_UNUSED_UNUSED) \ + _(2545, ZEND_VERIFY_NEVER_TYPE_SPEC_UNUSED_UNUSED) \ + _(2546, ZEND_CALLABLE_CONVERT_SPEC_UNUSED_UNUSED) \ + _(2547, ZEND_RECV_NOTYPE_SPEC) \ + _(2548, ZEND_JMP_FORWARD_SPEC) \ + _(2554, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ + _(2555, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2556, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2557, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2558, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2559, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2559, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ + _(2560, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2561, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2567, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2568, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2569, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2563, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2569, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ + _(2570, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2571, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2577, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ - _(2578, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2579, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2573, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2579, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ + _(2580, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2581, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2582, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ _(2583, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2584, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2584, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ + _(2585, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2586, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2592, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ - _(2593, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2594, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2588, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2594, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ + _(2595, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2596, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2602, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2603, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2604, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2598, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2604, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2605, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2606, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2607, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2608, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2609, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2609, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2610, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2611, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2617, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2618, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2619, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2613, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2619, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2620, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2621, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2623, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ - _(2624, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ + _(2623, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2625, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ _(2626, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ - _(2627, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2628, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2629, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2628, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ + _(2629, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ + _(2630, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2631, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2632, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2633, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2634, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2634, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ + _(2635, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2636, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2642, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2643, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2644, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2638, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2644, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ + _(2645, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2646, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2648, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ - _(2649, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ + _(2648, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2650, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ _(2651, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ - _(2652, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ - _(2653, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2654, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2653, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ + _(2654, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ + _(2655, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2656, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2657, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ _(2658, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2659, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2659, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ + _(2660, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2661, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2667, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ - _(2668, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2669, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2663, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2669, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ + _(2670, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2671, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2673, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(2674, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(2673, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2675, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ _(2676, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(2677, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2678, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2679, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2678, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(2679, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2680, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2681, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2682, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2683, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2684, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2684, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2685, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2686, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2692, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2693, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2694, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2688, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2694, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2695, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2696, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2702, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2703, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2704, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2698, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2704, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ + _(2705, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2706, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2707, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2708, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2709, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2709, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ + _(2710, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2711, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2717, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2718, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2719, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2713, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2719, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ + _(2720, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2721, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2727, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ - _(2728, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2729, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2723, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2729, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ + _(2730, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2731, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2732, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ _(2733, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2734, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2734, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ + _(2735, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2736, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2742, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ - _(2743, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2744, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2738, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2744, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ + _(2745, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2746, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2752, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2753, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2754, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2748, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2754, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2755, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2756, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2757, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2758, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2759, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2759, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2760, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2761, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2767, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2768, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2769, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2763, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2769, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2770, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2771, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2787, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2788, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2789, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2790, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2791, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2792, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2793, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2794, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2795, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2799, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2800, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2801, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2802, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2803, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2804, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2805, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2806, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2807, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2808, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2809, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2810, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2814, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2815, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2816, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2832, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2833, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2834, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2835, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2836, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2837, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2838, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2839, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2840, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2844, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2845, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2846, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2862, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2863, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2864, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2865, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2866, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2867, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2868, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2869, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2870, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2874, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2875, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2876, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2877, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2878, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2879, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2880, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2881, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2882, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2883, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2884, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2885, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2889, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2890, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2891, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2907, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2908, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2909, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2910, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2911, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2912, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2913, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2914, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2915, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2919, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2920, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2921, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2937, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2938, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2939, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2940, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2941, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2942, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2943, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2944, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2945, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2949, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2950, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2951, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2952, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2953, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2954, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2955, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2956, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2957, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2958, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2959, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2960, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2964, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2965, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2966, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2982, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2983, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2984, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2985, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2986, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2987, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2988, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2989, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2990, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2994, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2995, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2996, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3012, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3013, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3014, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3015, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3016, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3017, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3018, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3019, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3020, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3024, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3025, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3026, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3027, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3028, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3029, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3030, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3031, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3032, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3033, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3034, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3035, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3039, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3040, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3041, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3057, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3058, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3059, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3060, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3061, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3062, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3063, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3064, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3065, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3069, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3070, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3071, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3072, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ - _(3076, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV) \ - _(3077, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ - _(3081, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV) \ - _(3085, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ - _(3086, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3087, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3088, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ - _(3089, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3090, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3094, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ - _(3095, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3096, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3097, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3098, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3099, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3100, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3101, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3102, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3103, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3104, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3105, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3109, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3110, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3111, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3112, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3113, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3114, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3115, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3116, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3117, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3118, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3119, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3120, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3124, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3125, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3126, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3142, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3143, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3144, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3145, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3146, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3147, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3148, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3149, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3150, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3154, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3155, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3156, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3160, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3161, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3162, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3163, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3164, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3165, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3169, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3170, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3171, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3172, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3173, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3174, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3175, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3176, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3177, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3178, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3179, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3180, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3184, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3185, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3186, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3187, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3188, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3189, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3190, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3191, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3192, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3193, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3194, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3195, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3199, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3200, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3201, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3217, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3218, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3219, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3220, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3221, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3222, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3223, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3224, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3225, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3229, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3230, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3231, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3235, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ - _(3236, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3237, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3238, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ - _(3239, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3240, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3244, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ - _(3245, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3246, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3247, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3248, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3249, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3250, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3251, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3252, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3253, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3254, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3255, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3259, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3260, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3261, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3262, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3263, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3264, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3265, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3266, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3267, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3268, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3269, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3270, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3274, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3275, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3276, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3292, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3293, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3294, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3295, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3296, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3297, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3298, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3299, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3300, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3304, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3305, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3306, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3310, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3311, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3312, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3313, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3314, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3315, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3319, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3320, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3321, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3322, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3323, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3324, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3325, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3326, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3327, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3328, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3329, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3330, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3334, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3335, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3336, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3337, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3338, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3339, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3340, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3341, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3342, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3343, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3344, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3345, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3349, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3350, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3351, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3367, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3368, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3369, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3370, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3371, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3372, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3373, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3374, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3375, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3379, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3380, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3381, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3382, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ - _(3383, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ - _(3384, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_UNUSED) \ - _(3385, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_USED) \ - _(3386, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ - _(3387, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ - _(3388, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_UNUSED) \ - _(3389, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_USED) \ - _(3390, ZEND_POST_INC_LONG_NO_OVERFLOW_SPEC_CV) \ - _(3391, ZEND_POST_INC_LONG_SPEC_CV) \ - _(3392, ZEND_POST_DEC_LONG_NO_OVERFLOW_SPEC_CV) \ - _(3393, ZEND_POST_DEC_LONG_SPEC_CV) \ - _(3394, ZEND_QM_ASSIGN_LONG_SPEC_CONST) \ - _(3395, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ - _(3396, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ + _(2773, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2789, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2790, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2791, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2792, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2793, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2794, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2795, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2796, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2797, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2801, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2802, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2803, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2804, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2805, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2806, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2807, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2808, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2809, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2810, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2811, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2812, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2816, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2817, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2818, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2834, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2835, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2836, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2837, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2838, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2839, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2840, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2841, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2842, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2846, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2847, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2848, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2864, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2865, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2866, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2867, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2868, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2869, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2870, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2871, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2872, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2876, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2877, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2878, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2879, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2880, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2881, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2882, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2883, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2884, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2885, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2886, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2887, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2891, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2892, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2893, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2909, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2910, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2911, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2912, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2913, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2914, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2915, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2916, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2917, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2921, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2922, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2923, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2939, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2940, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2941, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2942, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2943, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2944, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2945, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2946, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2947, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2951, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2952, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2953, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2954, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2955, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2956, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2957, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2958, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2959, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2960, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2961, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2962, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2966, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2967, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2968, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2984, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2985, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2986, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2987, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2988, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2989, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2990, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2991, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2992, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2996, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2997, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2998, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3014, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3015, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3016, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3017, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3018, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3019, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3020, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3021, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3022, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3026, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3027, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3028, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3029, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3030, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3031, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3032, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3033, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3034, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3035, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3036, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3037, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3041, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3042, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3043, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3059, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3060, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3061, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3062, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3063, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3064, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3065, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3066, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3067, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3071, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3072, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3073, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3074, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ + _(3078, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV) \ + _(3079, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ + _(3083, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV) \ + _(3087, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ + _(3088, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3089, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3090, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ + _(3091, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3092, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3096, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ + _(3097, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3098, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3099, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3100, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3101, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3102, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3103, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3104, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3105, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3106, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3107, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3111, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3112, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3113, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3114, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3115, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3116, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3117, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3118, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3119, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3120, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3121, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3122, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3126, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3127, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3128, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3144, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3145, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3146, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3147, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3148, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3149, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3150, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3151, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3152, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3156, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3157, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3158, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3162, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3163, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3164, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3165, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3166, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3167, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3171, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3172, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3173, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3174, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3175, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3176, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3177, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3178, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3179, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3180, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3181, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3182, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3186, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3187, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3188, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3189, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3190, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3191, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3192, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3193, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3194, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3195, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3196, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3197, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3201, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3202, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3203, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3219, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3220, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3221, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3222, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3223, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3224, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3225, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3226, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3227, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3231, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3232, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3233, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3237, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ + _(3238, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3239, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3240, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ + _(3241, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3242, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3246, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ + _(3247, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3248, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3249, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3250, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3251, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3252, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3253, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3254, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3255, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3256, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3257, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3261, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3262, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3263, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3264, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3265, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3266, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3267, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3268, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3269, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3270, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3271, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3272, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3276, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3277, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3278, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3294, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3295, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3296, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3297, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3298, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3299, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3300, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3301, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3302, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3306, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3307, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3308, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3312, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3313, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3314, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3315, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3316, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3317, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3321, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3322, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3323, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3324, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3325, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3326, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3327, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3328, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3329, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3330, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3331, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3332, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3336, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3337, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3338, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3339, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3340, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3341, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3342, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3343, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3344, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3345, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3346, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3347, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3351, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3352, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3353, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3369, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3370, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3371, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3372, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3373, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3374, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3375, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3376, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3377, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3381, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3382, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3383, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3384, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ + _(3385, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ + _(3386, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_UNUSED) \ + _(3387, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_USED) \ + _(3388, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ + _(3389, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ + _(3390, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_UNUSED) \ + _(3391, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_USED) \ + _(3392, ZEND_POST_INC_LONG_NO_OVERFLOW_SPEC_CV) \ + _(3393, ZEND_POST_INC_LONG_SPEC_CV) \ + _(3394, ZEND_POST_DEC_LONG_NO_OVERFLOW_SPEC_CV) \ + _(3395, ZEND_POST_DEC_LONG_SPEC_CV) \ + _(3396, ZEND_QM_ASSIGN_LONG_SPEC_CONST) \ + _(3397, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ _(3398, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ - _(3399, ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST) \ - _(3400, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ - _(3401, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ + _(3400, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ + _(3401, ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST) \ + _(3402, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ _(3403, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ - _(3404, ZEND_QM_ASSIGN_NOREF_SPEC_CONST) \ - _(3405, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ - _(3406, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ + _(3405, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ + _(3406, ZEND_QM_ASSIGN_NOREF_SPEC_CONST) \ + _(3407, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ _(3408, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ - _(3410, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ - _(3411, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ + _(3410, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ + _(3412, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ _(3413, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ - _(3414, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ - _(3415, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3416, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3415, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ + _(3416, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ + _(3417, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ _(3418, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3419, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ _(3420, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3421, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3421, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ + _(3422, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ _(3423, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3429, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST) \ - _(3430, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ - _(3431, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ + _(3425, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3431, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST) \ + _(3432, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ _(3433, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ - _(3436, ZEND_SEND_VAR_SIMPLE_SPEC_VAR) \ - _(3438, ZEND_SEND_VAR_SIMPLE_SPEC_CV) \ - _(3441, ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED) \ - _(3443, ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED) \ - _(3444, ZEND_SEND_VAL_SIMPLE_SPEC_CONST) \ - _(3445, ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST) \ - _(3446, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED) \ - _(3447, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED) \ - _(3447+1, ZEND_NULL) + _(3435, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ + _(3438, ZEND_SEND_VAR_SIMPLE_SPEC_VAR) \ + _(3440, ZEND_SEND_VAR_SIMPLE_SPEC_CV) \ + _(3443, ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED) \ + _(3445, ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED) \ + _(3446, ZEND_SEND_VAL_SIMPLE_SPEC_CONST) \ + _(3447, ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST) \ + _(3448, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED) \ + _(3449, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED) \ + _(3449+1, ZEND_NULL) diff --git a/Zend/zend_weakrefs.c b/Zend/zend_weakrefs.c index 9d530047f902f..3f2e517f3fe4e 100644 --- a/Zend/zend_weakrefs.c +++ b/Zend/zend_weakrefs.c @@ -332,6 +332,7 @@ static zval *zend_weakmap_read_dimension(zend_object *object, zval *offset, int return NULL; } + ZVAL_DEREF(offset); if (Z_TYPE_P(offset) != IS_OBJECT) { zend_type_error("WeakMap key must be an object"); return NULL; @@ -362,6 +363,7 @@ static void zend_weakmap_write_dimension(zend_object *object, zval *offset, zval return; } + ZVAL_DEREF(offset); if (Z_TYPE_P(offset) != IS_OBJECT) { zend_type_error("WeakMap key must be an object"); return; @@ -390,6 +392,7 @@ static void zend_weakmap_write_dimension(zend_object *object, zval *offset, zval /* int return and check_empty due to Object Handler API */ static int zend_weakmap_has_dimension(zend_object *object, zval *offset, int check_empty) { + ZVAL_DEREF(offset); if (Z_TYPE_P(offset) != IS_OBJECT) { zend_type_error("WeakMap key must be an object"); return 0; @@ -409,6 +412,7 @@ static int zend_weakmap_has_dimension(zend_object *object, zval *offset, int che static void zend_weakmap_unset_dimension(zend_object *object, zval *offset) { + ZVAL_DEREF(offset); if (Z_TYPE_P(offset) != IS_OBJECT) { zend_type_error("WeakMap key must be an object"); return; @@ -424,7 +428,7 @@ static void zend_weakmap_unset_dimension(zend_object *object, zval *offset) zend_weakref_unregister(obj_addr, ZEND_WEAKREF_ENCODE(&wm->ht, ZEND_WEAKREF_TAG_MAP), 1); } -static int zend_weakmap_count_elements(zend_object *object, zend_long *count) +static zend_result zend_weakmap_count_elements(zend_object *object, zend_long *count) { zend_weakmap *wm = zend_weakmap_from(object); *count = zend_hash_num_elements(&wm->ht); diff --git a/azure-pipelines.yml b/azure-pipelines.yml index abb7c3f970923..1ae502c66f811 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -44,6 +44,12 @@ jobs: parameters: configurationName: I386_RELEASE_ZTS configurationParameters: '--disable-debug --enable-zts' + - template: azure/msan_job.yml + parameters: + configurationName: DEBUG_ZTS_MSAN + configurationParameters: '--enable-debug --enable-zts' + runTestsParameters: --msan + timeoutInMinutes: 90 - template: azure/community_job.yml parameters: configurationName: COMMUNITY @@ -51,11 +57,6 @@ jobs: --enable-debug --enable-zts --enable-address-sanitizer --enable-undefined-sanitizer CFLAGS='-fno-sanitize-recover' timeoutInMinutes: 90 - - template: azure/coverage_job.yml - parameters: - configurationName: COVERAGE_DEBUG_ZTS - configurationParameters: '--enable-debug --disable-zts' - timeoutInMinutes: 90 - template: azure/opcache_variation_job.yml parameters: configurationName: DEBUG_NTS_OPCACHE diff --git a/azure/coverage_job.yml b/azure/coverage_job.yml deleted file mode 100644 index a68b7af4f4aa1..0000000000000 --- a/azure/coverage_job.yml +++ /dev/null @@ -1,49 +0,0 @@ -parameters: - configurationName: '' - configurationParameters: '' - runTestsParameters: '' - timeoutInMinutes: 60 - -jobs: - - job: ${{ parameters.configurationName }} - timeoutInMinutes: ${{ parameters.timeoutInMinutes }} - pool: - vmImage: 'ubuntu-20.04' - steps: - - template: mssql.yml - - template: apt.yml - - script: | - sudo -H pip install gcovr - displayName: 'Install gcovr' - - template: configure.yml - parameters: - configurationParameters: --enable-gcov ${{ parameters.configurationParameters }} - - script: make -j$(/usr/bin/nproc) >/dev/null - displayName: 'Make Build' - - template: install.yml - - template: setup.yml - - template: test.yml - parameters: - configurationName: ${{ parameters.configurationName }} - runTestsParameters: ${{ parameters.runTestsParameters }} - - template: test.yml - parameters: - configurationName: ${{ parameters.configurationName }} - runTestsName: 'OpCache' - runTestsParameters: >- - ${{ parameters.runTestsParameters }} - -d zend_extension=opcache.so - - script: bash <(curl -s https://codecov.io/bash) - displayName: 'Upload ${{ parameters.configurationName }} Test Coverage to Codecov.io' - condition: or(succeeded(), failed()) - - script: | - make gcovr-xml - mv gcovr.xml coverage.xml - displayName: 'Generate ${{ parameters.configurationName }} Test Coverage Cobertura XML Report' - condition: or(succeeded(), failed()) - - task: PublishCodeCoverageResults@1 - inputs: - codeCoverageTool: 'Cobertura' - summaryFileLocation: coverage.xml - displayName: 'Publish ${{ parameters.configurationName }} Test Coverage' - condition: or(succeeded(), failed()) diff --git a/azure/libmysqlclient_job.yml b/azure/libmysqlclient_job.yml index 4eb998014c316..b44eb625f9567 100644 --- a/azure/libmysqlclient_job.yml +++ b/azure/libmysqlclient_job.yml @@ -32,6 +32,6 @@ jobs: libmysql: mysql-5.7.38-linux-glibc2.12-x86_64.tar.gz - template: libmysqlclient_test.yml parameters: - configurationName: ${{ parameters.configurationName }} - MySQL 8.0.27 - libmysql: mysql-8.0.27-linux-glibc2.12-x86_64.tar.xz + configurationName: ${{ parameters.configurationName }} - MySQL 8.0.30 + libmysql: mysql-8.0.30-linux-glibc2.12-x86_64.tar.xz configurationParameters: ${{ parameters.configurationParameters }} --enable-werror diff --git a/azure/libmysqlclient_test.yml b/azure/libmysqlclient_test.yml index ccf3912b005eb..059be219e2fe1 100644 --- a/azure/libmysqlclient_test.yml +++ b/azure/libmysqlclient_test.yml @@ -34,7 +34,7 @@ steps: export REPORT_EXIT_STATUS=no rm -rf junit.xml | true sapi/cli/php run-tests.php -P -q \ - -g FAIL,XFAIL,BORK,WARN,LEAK,XLEAK,SKIP \ + -g FAIL,BORK,LEAK,XLEAK \ --offline --show-diff --show-slow 1000 --set-timeout 120 \ ext/pdo_mysql displayName: 'Test ${{ parameters.configurationName }}' diff --git a/azure/test.yml b/azure/test.yml index 13fa12700d335..09028900ea21a 100644 --- a/azure/test.yml +++ b/azure/test.yml @@ -18,7 +18,7 @@ steps: rm -rf junit.xml | true sapi/cli/php run-tests.php -P -q \ -j$(/usr/bin/nproc) \ - -g FAIL,XFAIL,BORK,WARN,LEAK,XLEAK,SKIP \ + -g FAIL,BORK,LEAK,XLEAK \ --offline \ --show-diff \ --show-slow 1000 \ diff --git a/build/gen_stub.php b/build/gen_stub.php index 4fbda773d5a3d..3eb7c1c662a80 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -15,7 +15,13 @@ use PhpParser\PrettyPrinterAbstract; error_reporting(E_ALL); -ini_set("precision", "17"); +ini_set("precision", "-1"); + +const PHP_70_VERSION_ID = 70000; +const PHP_80_VERSION_ID = 80000; +const PHP_81_VERSION_ID = 80100; +const PHP_82_VERSION_ID = 80200; +const ALL_PHP_VERSION_IDS = [PHP_70_VERSION_ID, PHP_80_VERSION_ID, PHP_81_VERSION_ID, PHP_82_VERSION_ID]; /** * @return FileInfo[] @@ -46,28 +52,54 @@ function processDirectory(string $dir, Context $context): array { return $fileInfos; } -function processStubFile(string $stubFile, Context $context): ?FileInfo { +function processStubFile(string $stubFile, Context $context, bool $includeOnly = false): ?FileInfo { try { if (!file_exists($stubFile)) { throw new Exception("File $stubFile does not exist"); } - $stubFilenameWithoutExtension = str_replace(".stub.php", "", $stubFile); - $arginfoFile = "{$stubFilenameWithoutExtension}_arginfo.h"; - $legacyFile = "{$stubFilenameWithoutExtension}_legacy_arginfo.h"; + if (!$includeOnly) { + $stubFilenameWithoutExtension = str_replace(".stub.php", "", $stubFile); + $arginfoFile = "{$stubFilenameWithoutExtension}_arginfo.h"; + $legacyFile = "{$stubFilenameWithoutExtension}_legacy_arginfo.h"; - $stubCode = file_get_contents($stubFile); - $stubHash = computeStubHash($stubCode); - $oldStubHash = extractStubHash($arginfoFile); - if ($stubHash === $oldStubHash && !$context->forceParse) { - /* Stub file did not change, do not regenerate. */ - return null; + $stubCode = file_get_contents($stubFile); + $stubHash = computeStubHash($stubCode); + $oldStubHash = extractStubHash($arginfoFile); + if ($stubHash === $oldStubHash && !$context->forceParse) { + /* Stub file did not change, do not regenerate. */ + return null; + } + } + + if (!$fileInfo = $context->parsedFiles[$stubFile] ?? null) { + initPhpParser(); + $fileInfo = parseStubFile($stubCode ?? file_get_contents($stubFile)); + $context->parsedFiles[$stubFile] = $fileInfo; + + foreach ($fileInfo->dependencies as $dependency) { + // TODO add header search path for extensions? + $prefixes = [dirname($stubFile) . "/", dirname(__DIR__) . "/"]; + foreach ($prefixes as $prefix) { + $depFile = $prefix . $dependency; + if (file_exists($depFile)) { + break; + } + $depFile = null; + } + if (!$depFile) { + throw new Exception("File $stubFile includes a file $dependency which does not exist"); + } + processStubFile($depFile, $context, true); + } + + $constInfos = $fileInfo->getAllConstInfos(); + $context->allConstInfos = array_merge($context->allConstInfos, $constInfos); } - initPhpParser(); - $fileInfo = parseStubFile($stubCode); - $constInfos = $fileInfo->getAllConstInfos(); - $context->allConstInfos = array_merge($context->allConstInfos, $constInfos); + if ($includeOnly) { + return $fileInfo; + } $arginfoCode = generateArgInfoCode( basename($stubFilenameWithoutExtension), @@ -79,12 +111,15 @@ function processStubFile(string $stubFile, Context $context): ?FileInfo { echo "Saved $arginfoFile\n"; } - if ($fileInfo->generateLegacyArginfo) { + if ($fileInfo->generateLegacyArginfoForPhpVersionId !== null && $fileInfo->generateLegacyArginfoForPhpVersionId < PHP_80_VERSION_ID) { $legacyFileInfo = clone $fileInfo; foreach ($legacyFileInfo->getAllFuncInfos() as $funcInfo) { $funcInfo->discardInfoForOldPhpVersions(); } + foreach ($legacyFileInfo->getAllConstInfos() as $constInfo) { + $constInfo->discardInfoForOldPhpVersions(); + } foreach ($legacyFileInfo->getAllPropertyInfos() as $propertyInfo) { $propertyInfo->discardInfoForOldPhpVersions(); } @@ -130,13 +165,14 @@ class Context { /** @var bool */ public $forceRegeneration = false; /** @var iterable */ - public iterable $allConstInfos = []; + public $allConstInfos = []; + /** @var FileInfo[] */ + public $parsedFiles = []; } class ArrayType extends SimpleType { /** @var Type */ public $keyType; - /** @var Type */ public $valueType; @@ -188,6 +224,11 @@ public static function fromNode(Node $node): SimpleType { return new SimpleType($node->toLowerString(), true); } + if ($node->toLowerString() === 'true') { + // TODO PHP-Parser doesn't yet recognize true as a stand-alone built-in type + return new SimpleType($node->toLowerString(), true); + } + if ($node->toLowerString() === 'self') { throw new Exception('The exact class name must be used instead of "self"'); } @@ -380,6 +421,8 @@ public function toTypeCode(): string { return "IS_NULL"; case "false": return "IS_FALSE"; + case "true": + return "IS_TRUE"; default: throw new Exception("Not implemented: $this->name"); } @@ -393,6 +436,8 @@ public function toTypeMask(): string { return "MAY_BE_NULL"; case "false": return "MAY_BE_FALSE"; + case "true": + return "MAY_BE_TRUE"; case "bool": return "MAY_BE_BOOL"; case "int": @@ -443,6 +488,8 @@ public function toOptimizerTypeMaskForArrayValue(): string { return "MAY_BE_ARRAY_OF_NULL"; case "false": return "MAY_BE_ARRAY_OF_FALSE"; + case "true": + return "MAY_BE_ARRAY_OF_TRUE"; case "bool": return "MAY_BE_ARRAY_OF_FALSE|MAY_BE_ARRAY_OF_TRUE"; case "int": @@ -472,8 +519,6 @@ public function toOptimizerTypeMask(): string { } switch ($this->name) { - case "true": - return "MAY_BE_TRUE"; case "resource": return "MAY_BE_RESOURCE"; case "callable": @@ -488,7 +533,12 @@ public function toOptimizerTypeMask(): string { } public function toEscapedName(): string { - return str_replace('\\', '\\\\', $this->name); + // Escape backslashes, and also encode \u and \U to avoid compilation errors in generated macros + return str_replace( + ['\\', '\\u', '\\U'], + ['\\\\', '\\\\165', '\\\\125'], + $this->name + ); } public function toVarEscapedName(): string { @@ -503,15 +553,17 @@ public function equals(SimpleType $other): bool { class Type { /** @var SimpleType[] */ public $types; + /** @var bool */ + public $isIntersection = false; public static function fromNode(Node $node): Type { - if ($node instanceof Node\UnionType) { + if ($node instanceof Node\UnionType || $node instanceof Node\IntersectionType) { $nestedTypeObjects = array_map(['Type', 'fromNode'], $node->types); $types = []; foreach ($nestedTypeObjects as $typeObject) { array_push($types, ...$typeObject->types); } - return new Type($types); + return new Type($types, ($node instanceof Node\IntersectionType)); } if ($node instanceof Node\NullableType) { @@ -519,7 +571,8 @@ public static function fromNode(Node $node): Type { [ ...Type::fromNode($node->type)->types, SimpleType::null(), - ] + ], + false ); } @@ -528,11 +581,12 @@ public static function fromNode(Node $node): Type { [ SimpleType::fromString("Traversable"), ArrayType::createGenericArray(), - ] + ], + false ); } - return new Type([SimpleType::fromNode($node)]); + return new Type([SimpleType::fromNode($node)], false); } public static function fromString(string $typeString): self { @@ -540,6 +594,7 @@ public static function fromString(string $typeString): self { $simpleTypes = []; $simpleTypeOffset = 0; $inArray = false; + $isIntersection = false; $typeStringLength = strlen($typeString); for ($i = 0; $i < $typeStringLength; $i++) { @@ -559,7 +614,8 @@ public static function fromString(string $typeString): self { continue; } - if ($char === "|") { + if ($char === "|" || $char === "&") { + $isIntersection = ($char === "&"); $simpleTypeName = trim(substr($typeString, $simpleTypeOffset, $i - $simpleTypeOffset)); $simpleTypes[] = SimpleType::fromString($simpleTypeName); @@ -568,14 +624,15 @@ public static function fromString(string $typeString): self { } } - return new Type($simpleTypes); + return new Type($simpleTypes, $isIntersection); } /** * @param SimpleType[] $types */ - private function __construct(array $types) { + private function __construct(array $types, bool $isIntersection) { $this->types = $types; + $this->isIntersection = $isIntersection; } public function isScalar(): bool { @@ -605,7 +662,8 @@ public function getWithoutNull(): Type { function(SimpleType $type) { return !$type->isNull(); } - ) + ), + false ); } @@ -638,6 +696,7 @@ public function toOptimizerTypeMask(): string { $optimizerTypes = []; foreach ($this->types as $type) { + // TODO Support for toOptimizerMask for intersection $optimizerTypes[] = $type->toOptimizerTypeMask(); } @@ -666,8 +725,9 @@ public function toOptimizerTypeMaskForArrayValue(): string { public function getTypeForDoc(DOMDocument $doc): DOMElement { if (count($this->types) > 1) { + $typeSort = $this->isIntersection ? "intersection" : "union"; $typeElement = $doc->createElement('type'); - $typeElement->setAttribute("class", "union"); + $typeElement->setAttribute("class", $typeSort); foreach ($this->types as $type) { $unionTypeElement = $doc->createElement('type', $type->name); @@ -710,7 +770,8 @@ public function __toString() { return 'mixed'; } - return implode('|', array_map( + $char = $this->isIntersection ? '&' : '|'; + return implode($char, array_map( function ($type) { return $type->name; }, $this->types) ); @@ -770,9 +831,12 @@ class ArgInfo { public $phpDocType; /** @var string|null */ public $defaultValue; - /** @var bool */ - public $isSensitive; + /** @var AttributeInfo[] */ + public $attributes; + /** + * @param AttributeInfo[] $attributes + */ public function __construct( string $name, int $sendBy, @@ -780,14 +844,14 @@ public function __construct( ?Type $type, ?Type $phpDocType, ?string $defaultValue, - bool $isSensitive + array $attributes ) { $this->name = $name; $this->sendBy = $sendBy; $this->isVariadic = $isVariadic; $this->setTypes($type, $phpDocType); $this->defaultValue = $defaultValue; - $this->isSensitive = $isSensitive; + $this->attributes = $attributes; } public function equals(ArgInfo $other): bool { @@ -795,8 +859,7 @@ public function equals(ArgInfo $other): bool { && $this->sendBy === $other->sendBy && $this->isVariadic === $other->isVariadic && Type::equals($this->type, $other->type) - && $this->defaultValue === $other->defaultValue - && $this->isSensitive === $other->isSensitive; + && $this->defaultValue === $other->defaultValue; } public function getSendByString(): string { @@ -854,10 +917,6 @@ public function getDefaultValueAsMethodSynopsisString(): ?string { private function setTypes(?Type $type, ?Type $phpDocType): void { - if ($phpDocType !== null && Type::equals($type, $phpDocType)) { - throw new Exception('PHPDoc param type "' . $phpDocType->__toString() . '" is unnecessary'); - } - $this->type = $type; $this->phpDocType = $phpDocType; } @@ -1103,10 +1162,6 @@ public function getMethodSynopsisType(): ?Type { private function setTypes(?Type $type, ?Type $phpDocType, bool $tentativeReturnType): void { - if ($phpDocType !== null && Type::equals($type, $phpDocType)) { - throw new Exception('PHPDoc return type "' . $phpDocType->__toString() . '" is unnecessary'); - } - $this->type = $type; $this->phpDocType = $phpDocType; $this->tentativeReturnType = $tentativeReturnType; @@ -1389,6 +1444,7 @@ public function discardInfoForOldPhpVersions(): void { foreach ($this->args as $arg) { $arg->type = null; $arg->defaultValue = null; + $arg->attributes = []; } } @@ -1546,7 +1602,7 @@ class EvaluatedValue public $type; /** @var string|null */ - public $cConstName; + public $cConstValue; /** @var bool */ public $isUnknownConstValue; @@ -1623,7 +1679,7 @@ private function __construct($value, SimpleType $type, ?string $cConstName, ?Con { $this->value = $value; $this->type = $type; - $this->cConstName = $cConstName; + $this->cConstValue = $cConstName; $this->originatingConst = $originatingConst; $this->isUnknownConstValue = $isUnknownConstValue; } @@ -1640,7 +1696,7 @@ public function initializeZval(string $zvalName, iterable $allConstInfos): strin if ($this->type->isNull()) { $code .= "\tZVAL_NULL(&$zvalName);\n"; } elseif ($this->type->isBool()) { - $code .= "\tZVAL_BOOL(&$zvalName, " . ($cConstValue ?: ($this->value ? "true" : "false")) . ");\n"; + $code .= "\t" . ($this->value ? 'ZVAL_TRUE' : 'ZVAL_FALSE') . "(&$zvalName);\n"; } elseif ($this->type->isInt()) { $code .= "\tZVAL_LONG(&$zvalName, " . ($cConstValue ?: $this->value) . ");\n"; } elseif ($this->type->isFloat()) { @@ -1671,8 +1727,8 @@ public function initializeZval(string $zvalName, iterable $allConstInfos): strin */ public function getCConstValue(iterable $allConstInfos): ?string { - if ($this->cConstName) { - return $this->cConstName; + if ($this->cConstValue) { + return $this->cConstValue; } if ($this->originatingConst) { @@ -1687,12 +1743,24 @@ abstract class VariableLike { /** @var Type|null */ public $phpDocType; - /** @var int */ public $flags; - /** @var string|null */ public $link; + /** @var int|null */ + public $phpVersionIdMinimumCompatibility; + + public function __construct( + int $flags, + ?Type $phpDocType, + ?string $link, + ?int $phpVersionIdMinimumCompatibility + ) { + $this->flags = $flags; + $this->phpDocType = $phpDocType; + $this->link = $link; + $this->phpVersionIdMinimumCompatibility = $phpVersionIdMinimumCompatibility; + } abstract protected function getVariableTypeCode(): string; @@ -1711,7 +1779,12 @@ abstract protected function getFieldSynopsisName(): string; */ abstract protected function getFieldSynopsisValueString(iterable $allConstInfos): ?string; - protected function getFlagsAsString(): string + abstract public function discardInfoForOldPhpVersions(): void; + + /** + * @return array + */ + protected function getFlagsByPhpVersion(): array { $flags = "ZEND_ACC_PUBLIC"; if ($this->flags & Class_::MODIFIER_PROTECTED) { @@ -1720,7 +1793,12 @@ protected function getFlagsAsString(): string $flags = "ZEND_ACC_PRIVATE"; } - return $flags; + return [ + PHP_70_VERSION_ID => [$flags], + PHP_80_VERSION_ID => [$flags], + PHP_81_VERSION_ID => [$flags], + PHP_82_VERSION_ID => [$flags], + ]; } /** @@ -1769,6 +1847,24 @@ protected function addModifiersToFieldSynopsis(DOMDocument $doc, DOMElement $fie $fieldsynopsisElement->appendChild($doc->createElement("modifier", "private")); } } + + /** + * @param array $flags + * @return array + */ + protected function addFlagForVersionsAbove(array $flags, string $flag, int $minimumVersionId): array + { + $write = false; + + foreach ($flags as $version => $versionFlags) { + if ($version === $minimumVersionId || $write === true) { + $flags[$version][] = $flag; + $write = true; + } + } + + return $flags; + } } class ConstInfo extends VariableLike @@ -1784,7 +1880,7 @@ class ConstInfo extends VariableLike /** @var string|null */ public $cond; /** @var string|null */ - public $cname; + public $cValue; public function __construct( ConstOrClassConstName $name, @@ -1794,18 +1890,17 @@ public function __construct( ?Type $phpDocType, bool $isDeprecated, ?string $cond, - ?string $cname, - ?string $link + ?string $cValue, + ?string $link, + ?int $phpVersionIdMinimumCompatibility ) { $this->name = $name; - $this->flags = $flags; $this->value = $value; $this->valueString = $valueString; - $this->phpDocType = $phpDocType; $this->isDeprecated = $isDeprecated; $this->cond = $cond; - $this->cname = $cname; - $this->link = $link; + $this->cValue = $cValue; + parent::__construct($flags, $phpDocType, $link, $phpVersionIdMinimumCompatibility); } /** @@ -1816,7 +1911,7 @@ public function getValue(iterable $allConstInfos): EvaluatedValue return EvaluatedValue::createFromExpression( $this->value, $this->phpDocType->tryToSimpleType(), - $this->cname, + $this->cValue, $allConstInfos ); } @@ -1861,7 +1956,7 @@ protected function addTypeToFieldSynopsis(DOMDocument $doc, DOMElement $fieldsyn */ protected function getFieldSynopsisValueString(iterable $allConstInfos): ?string { - $value = EvaluatedValue::createFromExpression($this->value, null, $this->cname, $allConstInfos); + $value = EvaluatedValue::createFromExpression($this->value, null, $this->cValue, $allConstInfos); if ($value->originatingConst) { return $value->originatingConst->getFieldSynopsisValueString($allConstInfos); } @@ -1869,6 +1964,11 @@ protected function getFieldSynopsisValueString(iterable $allConstInfos): ?string return $this->valueString; } + public function discardInfoForOldPhpVersions(): void { + $this->flags &= ~Class_::MODIFIER_FINAL; + $this->isDeprecated = false; + } + /** * @param iterable $allConstInfos */ @@ -1879,9 +1979,9 @@ public function getDeclaration(iterable $allConstInfos): string throw new Exception("Constant " . $this->name->__toString() . " must have a simple built-in type"); } - $value = EvaluatedValue::createFromExpression($this->value, $type, $this->cname, $allConstInfos); - if ($value->isUnknownConstValue && !$value->cConstName) { - throw new Exception("Constant " . $this->name->__toString() . " must have a @cname annotation"); + $value = EvaluatedValue::createFromExpression($this->value, $type, $this->cValue, $allConstInfos); + if ($value->isUnknownConstValue && !$value->cConstValue) { + throw new Exception("Constant " . $this->name->__toString() . " must have a @cvalue annotation"); } $code = ""; @@ -1953,7 +2053,13 @@ private function getClassConstDeclaration(EvaluatedValue $value, iterable $allCo $code .= "\tzend_string *const_{$constName}_name = zend_string_init_interned(\"$constName\", sizeof(\"$constName\") - 1, 1);\n"; $nameCode = "const_{$constName}_name"; - $code .= "\tzend_declare_class_constant_ex(class_entry, $nameCode, &const_{$constName}_value, " . $this->getFlagsAsString() . ", NULL);\n"; + $template = "\tzend_declare_class_constant_ex(class_entry, $nameCode, &const_{$constName}_value, %s, NULL);\n"; + $flagsCode = generateVersionDependentFlagCode( + $template, + $this->getFlagsByPhpVersion(), + $this->phpVersionIdMinimumCompatibility + ); + $code .= implode("", $flagsCode); $code .= "\tzend_string_release(const_{$constName}_name);\n"; return $code; @@ -1961,50 +2067,53 @@ private function getClassConstDeclaration(EvaluatedValue $value, iterable $allCo private function getValueAssertion(EvaluatedValue $value): string { - if ($value->isUnknownConstValue || $value->originatingConst || $value->cConstName === null) { + if ($value->isUnknownConstValue || $value->originatingConst || $value->cConstValue === null) { return ""; } - $cName = $value->cConstName; + $cConstValue = $value->cConstValue; $constValue = $value->value; if ($value->type->isNull()) { - return "\tZEND_ASSERT($cName == NULL);\n"; + return "\tZEND_ASSERT($cConstValue == NULL);\n"; } if ($value->type->isBool()) { $cValue = $constValue ? "true" : "false"; - return "\tZEND_ASSERT($cName == $cValue);\n"; + return "\tZEND_ASSERT($cConstValue == $cValue);\n"; } if ($value->type->isInt()) { $cValue = (int) $constValue; - return "\tZEND_ASSERT($cName == $cValue);\n"; + return "\tZEND_ASSERT($cConstValue == $cValue);\n"; } if ($value->type->isFloat()) { $cValue = (float) $constValue; - return "\tZEND_ASSERT($cName == $cValue);\n"; + return "\tZEND_ASSERT($cConstValue == $cValue);\n"; } if ($value->type->isString()) { $cValue = '"' . addslashes($constValue) . '"'; - return "\tZEND_ASSERT(strcmp($cName, $cValue) == 0);\n"; + return "\tZEND_ASSERT(strcmp($cConstValue, $cValue) == 0);\n"; } throw new Exception("Unimplemented constant type"); } - protected function getFlagsAsString(): string + /** + * @return array + */ + protected function getFlagsByPhpVersion(): array { - $flags = parent::getFlagsAsString(); + $flags = parent::getFlagsByPhpVersion(); - if ($this->flags & Class_::MODIFIER_FINAL) { - $flags .= "|ZEND_ACC_FINAL"; + if ($this->isDeprecated) { + $flags = $this->addFlagForVersionsAbove($flags, "ZEND_ACC_DEPRECATED", PHP_80_VERSION_ID); } - if ($this->isDeprecated) { - $flags .= "|ZEND_ACC_DEPRECATED"; + if ($this->flags & Class_::MODIFIER_FINAL) { + $flags = $this->addFlagForVersionsAbove($flags, "ZEND_ACC_FINAL", PHP_81_VERSION_ID); } return $flags; @@ -2045,16 +2154,15 @@ public function __construct( ?Expr $defaultValue, ?string $defaultValueString, bool $isDocReadonly, - ?string $link + ?string $link, + ?int $phpVersionIdMinimumCompatibility ) { $this->name = $name; - $this->flags = $flags; $this->type = $type; - $this->phpDocType = $phpDocType; $this->defaultValue = $defaultValue; $this->defaultValueString = $defaultValueString; $this->isDocReadonly = $isDocReadonly; - $this->link = $link; + parent::__construct($flags, $phpDocType, $link, $phpVersionIdMinimumCompatibility); } protected function getVariableTypeCode(): string @@ -2094,6 +2202,7 @@ protected function getFieldSynopsisValueString(iterable $allConstInfos): ?string public function discardInfoForOldPhpVersions(): void { $this->type = null; + $this->flags &= ~Class_::MODIFIER_READONLY; } /** @@ -2136,7 +2245,11 @@ public function getDeclaration(iterable $allConstInfos): string { $typeMaskCode = $this->type->toArginfoType()->toTypeMask(); - $code .= "\tzend_type property_{$propertyName}_type = ZEND_TYPE_INIT_UNION(property_{$propertyName}_type_list, $typeMaskCode);\n"; + if ($this->type->isIntersection) { + $code .= "\tzend_type property_{$propertyName}_type = ZEND_TYPE_INIT_INTERSECTION(property_{$propertyName}_type_list, $typeMaskCode);\n"; + } else { + $code .= "\tzend_type property_{$propertyName}_type = ZEND_TYPE_INIT_UNION(property_{$propertyName}_type_list, $typeMaskCode);\n"; + } $typeCode = "property_{$propertyName}_type"; } else { $escapedClassName = $arginfoType->classTypes[0]->toEscapedName(); @@ -2161,25 +2274,35 @@ public function getDeclaration(iterable $allConstInfos): string { $nameCode = "property_{$propertyName}_name"; if ($this->type !== null) { - $code .= "\tzend_declare_typed_property(class_entry, $nameCode, &$zvalName, " . $this->getFlagsAsString() . ", NULL, $typeCode);\n"; + $template = "\tzend_declare_typed_property(class_entry, $nameCode, &$zvalName, %s, NULL, $typeCode);\n"; } else { - $code .= "\tzend_declare_property_ex(class_entry, $nameCode, &$zvalName, " . $this->getFlagsAsString() . ", NULL);\n"; + $template = "\tzend_declare_property_ex(class_entry, $nameCode, &$zvalName, %s, NULL);\n"; } + $flagsCode = generateVersionDependentFlagCode( + $template, + $this->getFlagsByPhpVersion(), + $this->phpVersionIdMinimumCompatibility + ); + $code .= implode("", $flagsCode); + $code .= "\tzend_string_release(property_{$propertyName}_name);\n"; return $code; } - protected function getFlagsAsString(): string + /** + * @return array + */ + protected function getFlagsByPhpVersion(): array { - $flags = parent::getFlagsAsString(); + $flags = parent::getFlagsByPhpVersion(); if ($this->flags & Class_::MODIFIER_STATIC) { - $flags .= "|ZEND_ACC_STATIC"; + $flags = $this->addFlagForVersionsAbove($flags, "ZEND_ACC_STATIC", PHP_70_VERSION_ID); } if ($this->flags & Class_::MODIFIER_READONLY) { - $flags .= "|ZEND_ACC_READONLY"; + $flags = $this->addFlagForVersionsAbove($flags, "ZEND_ACC_READONLY", PHP_81_VERSION_ID); } return $flags; @@ -2248,6 +2371,46 @@ public function getDeclaration(iterable $allConstInfos): string { } } +class AttributeInfo { + /** @var string */ + public $class; + /** @var \PhpParser\Node\Arg[] */ + public $args; + + /** @param \PhpParser\Node\Arg[] $args */ + public function __construct(string $class, array $args) { + $this->class = $class; + $this->args = $args; + } + + /** @param iterable $allConstInfos */ + public function generateCode(string $invocation, string $nameSuffix, iterable $allConstInfos): string { + /* see ZEND_KNOWN_STRINGS in Zend/strings.h */ + static $knowns = [ + "SensitiveParameter" => "ZEND_STR_SENSITIVEPARAMETER", + ]; + $code = "\n"; + $escapedAttributeName = strtr($this->class, '\\', '_'); + if (isset($knowns[$escapedAttributeName])) { + $code .= "\t" . ($this->args ? "zend_attribute *attribute_{$escapedAttributeName}_$nameSuffix = " : "") . "$invocation, ZSTR_KNOWN({$knowns[$escapedAttributeName]}), " . count($this->args) . ");\n"; + } else { + $code .= "\tzend_string *attribute_name_{$escapedAttributeName}_$nameSuffix = zend_string_init_interned(\"" . addcslashes($this->class, "\\") . "\", sizeof(\"" . addcslashes($this->class, "\\") . "\") - 1, 1);\n"; + $code .= "\t" . ($this->args ? "zend_attribute *attribute_{$escapedAttributeName}_$nameSuffix = " : "") . "$invocation, attribute_name_{$escapedAttributeName}_$nameSuffix, " . count($this->args) . ");\n"; + $code .= "\tzend_string_release(attribute_name_{$escapedAttributeName}_$nameSuffix);\n"; + } + foreach ($this->args as $i => $arg) { + $value = EvaluatedValue::createFromExpression($arg->value, null, null, $allConstInfos); + $zvalName = "attribute_{$escapedAttributeName}_{$nameSuffix}_arg$i"; + $code .= $value->initializeZval($zvalName, $allConstInfos); + $code .= "\tZVAL_COPY_VALUE(&attribute_{$escapedAttributeName}_{$nameSuffix}->args[$i].value, &$zvalName);\n"; + if ($arg->name) { + $code .= "\tattribute_{$escapedAttributeName}_{$nameSuffix}->args[$i].name = zend_string_init(\"{$arg->name->name}\", sizeof(\"{$arg->name->name}\") - 1, 1);\n"; + } + } + return $code; + } +} + class ClassInfo { /** @var Name */ public $name; @@ -2263,6 +2426,8 @@ class ClassInfo { public $isDeprecated; /** @var bool */ public $isStrictProperties; + /** @var AttributeInfo[] */ + public $attributes; /** @var bool */ public $isNotSerializable; /** @var Name[] */ @@ -2279,8 +2444,11 @@ class ClassInfo { public $enumCaseInfos; /** @var string|null */ public $cond; + /** @var int|null */ + public $phpVersionIdMinimumCompatibility; /** + * @param AttributeInfo[] $attributes * @param Name[] $extends * @param Name[] $implements * @param ConstInfo[] $constInfos @@ -2296,6 +2464,7 @@ public function __construct( ?SimpleType $enumBackingType, bool $isDeprecated, bool $isStrictProperties, + array $attributes, bool $isNotSerializable, array $extends, array $implements, @@ -2303,7 +2472,8 @@ public function __construct( array $propertyInfos, array $funcInfos, array $enumCaseInfos, - ?string $cond + ?string $cond, + ?int $minimumPhpVersionIdCompatibility ) { $this->name = $name; $this->flags = $flags; @@ -2312,6 +2482,7 @@ public function __construct( $this->enumBackingType = $enumBackingType; $this->isDeprecated = $isDeprecated; $this->isStrictProperties = $isStrictProperties; + $this->attributes = $attributes; $this->isNotSerializable = $isNotSerializable; $this->extends = $extends; $this->implements = $implements; @@ -2320,6 +2491,7 @@ public function __construct( $this->funcInfos = $funcInfos; $this->enumCaseInfos = $enumCaseInfos; $this->cond = $cond; + $this->phpVersionIdMinimumCompatibility = $minimumPhpVersionIdCompatibility; } /** @@ -2339,6 +2511,13 @@ public function getRegistration(iterable $allConstInfos): string $code = ''; + $php81MinimumCompatibility = $this->phpVersionIdMinimumCompatibility === null || $this->phpVersionIdMinimumCompatibility >= PHP_81_VERSION_ID; + $php82MinimumCompatibility = $this->phpVersionIdMinimumCompatibility === null || $this->phpVersionIdMinimumCompatibility >= PHP_82_VERSION_ID; + + if ($this->type === "enum" && !$php81MinimumCompatibility) { + $code .= "#if (PHP_VERSION_ID >= " . PHP_81_VERSION_ID . ")\n"; + } + if ($this->cond) { $code .= "#if {$this->cond}\n"; } @@ -2346,7 +2525,7 @@ public function getRegistration(iterable $allConstInfos): string $code .= "static zend_class_entry *register_class_$escapedName(" . (empty($params) ? "void" : implode(", ", $params)) . ")\n"; $code .= "{\n"; - if ($this->type == "enum") { + if ($this->type === "enum") { $name = addslashes((string) $this->name); $backingType = $this->enumBackingType ? $this->enumBackingType->toTypeCode() : "IS_UNDEF"; @@ -2369,9 +2548,8 @@ public function getRegistration(iterable $allConstInfos): string } } - if ($this->getFlagsAsString()) { - $code .= "\tclass_entry->ce_flags |= " . $this->getFlagsAsString() . ";\n"; - } + $flagCodes = generateVersionDependentFlagCode("\tclass_entry->ce_flags |= %s;\n", $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility); + $code .= implode("", $flagCodes); $implements = array_map( function (Name $item) { @@ -2400,8 +2578,30 @@ function (Name $item) { $code .= $property->getDeclaration($allConstInfos); } - if ($attributeInitializationCode = generateAttributeInitialization($this->funcInfos, $this->cond)) { + if (!empty($this->attributes)) { + if (!$php82MinimumCompatibility) { + $code .= "\n#if (PHP_VERSION_ID >= " . PHP_82_VERSION_ID . ")"; + } + + foreach ($this->attributes as $attribute) { + $code .= $attribute->generateCode("zend_add_class_attribute(class_entry", "class_$escapedName", $allConstInfos); + } + + if (!$php82MinimumCompatibility) { + $code .= "#endif\n"; + } + } + + if ($attributeInitializationCode = generateAttributeInitialization($this->funcInfos, $allConstInfos, $this->cond)) { + if (!$php82MinimumCompatibility) { + $code .= "#if (PHP_VERSION_ID >= " . PHP_82_VERSION_ID . ")\n"; + } + $code .= "\n" . $attributeInitializationCode; + + if (!$php82MinimumCompatibility) { + $code .= "#endif\n"; + } } $code .= "\n\treturn class_entry;\n"; @@ -2412,42 +2612,67 @@ function (Name $item) { $code .= "#endif\n"; } + if ($this->type === "enum" && !$php81MinimumCompatibility) { + $code .= "#endif\n"; + } + return $code; } - private function getFlagsAsString(): string + /** + * @return array + */ + private function getFlagsByPhpVersion(): array { - $flags = []; + $php70Flags = []; if ($this->type === "trait") { - $flags[] = "ZEND_ACC_TRAIT"; + $php70Flags[] = "ZEND_ACC_TRAIT"; } if ($this->flags & Class_::MODIFIER_FINAL) { - $flags[] = "ZEND_ACC_FINAL"; + $php70Flags[] = "ZEND_ACC_FINAL"; } if ($this->flags & Class_::MODIFIER_ABSTRACT) { - $flags[] = "ZEND_ACC_ABSTRACT"; - } - - if ($this->flags & Class_::MODIFIER_READONLY) { - $flags[] = "ZEND_ACC_READONLY_CLASS"; + $php70Flags[] = "ZEND_ACC_ABSTRACT"; } if ($this->isDeprecated) { - $flags[] = "ZEND_ACC_DEPRECATED"; + $php70Flags[] = "ZEND_ACC_DEPRECATED"; } + $php80Flags = $php70Flags; + if ($this->isStrictProperties) { - $flags[] = "ZEND_ACC_NO_DYNAMIC_PROPERTIES"; + $php80Flags[] = "ZEND_ACC_NO_DYNAMIC_PROPERTIES"; } + $php81Flags = $php80Flags; + if ($this->isNotSerializable) { - $flags[] = "ZEND_ACC_NOT_SERIALIZABLE"; + $php81Flags[] = "ZEND_ACC_NOT_SERIALIZABLE"; + } + + $php82Flags = $php81Flags; + + if ($this->flags & Class_::MODIFIER_READONLY) { + $php82Flags[] = "ZEND_ACC_READONLY_CLASS"; } - return implode("|", $flags); + foreach ($this->attributes as $attr) { + if ($attr->class === "AllowDynamicProperties") { + $php82Flags[] = "ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES"; + break; + } + } + + return [ + PHP_70_VERSION_ID => $php70Flags, + PHP_80_VERSION_ID => $php80Flags, + PHP_81_VERSION_ID => $php81Flags, + PHP_82_VERSION_ID => $php82Flags, + ]; } /** @@ -2748,7 +2973,7 @@ private function collectInheritedMembers( $parentInfo->collectInheritedMembers( $parentsWithInheritedConstants, $unusedParentsWithInheritedProperties, - $parentsWithInheritedMethods, + $unusedParentsWithInheritedMethods, $classMap ); } @@ -2840,6 +3065,8 @@ private function appendInheritedMemberSectionToClassSynopsis(DOMDocument $doc, D } class FileInfo { + /** @var string[] */ + public $dependencies = []; /** @var ConstInfo[] */ public $constInfos = []; /** @var FuncInfo[] */ @@ -2850,8 +3077,8 @@ class FileInfo { public $generateFunctionEntries = false; /** @var string */ public $declarationPrefix = ""; - /** @var bool */ - public $generateLegacyArginfo = false; + /** @var int|null */ + public $generateLegacyArginfoForPhpVersionId; /** @var bool */ public $generateClassEntries = false; @@ -2946,7 +3173,7 @@ public function getVariableName(): string { if ($this->name === "param") { preg_match('/^\s*[\w\|\\\\\[\]]+\s*\$(\w+).*$/', $value, $matches); - } elseif ($this->name === "prefer-ref" || $this->name === "sensitive-param") { + } elseif ($this->name === "prefer-ref") { preg_match('/^\s*\$(\w+).*$/', $value, $matches); } @@ -3037,7 +3264,6 @@ function parseFunctionLike( break; case 'prefer-ref': - case 'sensitive-param': $varName = $tag->getVariableName(); if (!isset($paramMeta[$varName])) { $paramMeta[$varName] = []; @@ -3055,7 +3281,12 @@ function parseFunctionLike( foreach ($func->getParams() as $i => $param) { $varName = $param->var->name; $preferRef = !empty($paramMeta[$varName]['prefer-ref']); - $isSensitive = !empty($paramMeta[$varName]['sensitive-param']); + $attributes = []; + foreach ($param->attrGroups as $attrGroup) { + foreach ($attrGroup->attrs as $attr) { + $attributes[] = new AttributeInfo($attr->name->toString(), $attr->args); + } + } unset($paramMeta[$varName]); if (isset($varNameSet[$varName])) { @@ -3103,7 +3334,7 @@ function parseFunctionLike( $type, isset($docParamTypes[$varName]) ? Type::fromString($docParamTypes[$varName]) : null, $param->default ? $prettyPrinter->prettyPrintExpr($param->default) : null, - $isSensitive + $attributes ); if (!$param->default && !$param->variadic) { $numRequiredArgs = $i + 1; @@ -3152,11 +3383,12 @@ function parseConstLike( Node\Const_ $const, int $flags, ?DocComment $docComment, - ?string $cond + ?string $cond, + ?int $phpVersionIdMinimumCompatibility ): ConstInfo { $phpDocType = null; $deprecated = false; - $cname = null; + $cValue = null; $link = null; if ($docComment) { $tags = parseDocComment($docComment); @@ -3165,8 +3397,8 @@ function parseConstLike( $phpDocType = $tag->getType(); } elseif ($tag->name === 'deprecated') { $deprecated = true; - } elseif ($tag->name === 'cname') { - $cname = $tag->value; + } elseif ($tag->name === 'cvalue') { + $cValue = $tag->value; } elseif ($tag->name === 'link') { $link = $tag->value; } @@ -3185,8 +3417,9 @@ function parseConstLike( Type::fromString($phpDocType), $deprecated, $cond, - $cname, - $link + $cValue, + $link, + $phpVersionIdMinimumCompatibility ); } @@ -3196,7 +3429,8 @@ function parseProperty( Stmt\PropertyProperty $property, ?Node $type, ?DocComment $comment, - PrettyPrinterAbstract $prettyPrinter + PrettyPrinterAbstract $prettyPrinter, + ?int $phpVersionIdMinimumCompatibility ): PropertyInfo { $phpDocType = null; $isDocReadonly = false; @@ -3239,7 +3473,8 @@ function parseProperty( $property->default, $property->default ? $prettyPrinter->prettyPrintExpr($property->default) : null, $isDocReadonly, - $link + $link, + $phpVersionIdMinimumCompatibility ); } @@ -3256,7 +3491,8 @@ function parseClass( array $properties, array $methods, array $enumCases, - ?string $cond + ?string $cond, + ?int $minimumPhpVersionIdCompatibility ): ClassInfo { $flags = $class instanceof Class_ ? $class->flags : 0; $comment = $class->getDocComment(); @@ -3264,6 +3500,8 @@ function parseClass( $isDeprecated = false; $isStrictProperties = false; $isNotSerializable = false; + $allowsDynamicProperties = false; + $attributes = []; if ($comment) { $tags = parseDocComment($comment); @@ -3280,6 +3518,21 @@ function parseClass( } } + foreach ($class->attrGroups as $attrGroup) { + foreach ($attrGroup->attrs as $attr) { + $attributes[] = new AttributeInfo($attr->name->toString(), $attr->args); + switch ($attr->name->toString()) { + case 'AllowDynamicProperties': + $allowsDynamicProperties = true; + break; + } + } + } + + if ($isStrictProperties && $allowsDynamicProperties) { + throw new Exception("A class may not have '@strict-properties' and '#[\\AllowDynamicProperties]' at the same time."); + } + $extends = []; $implements = []; @@ -3310,6 +3563,7 @@ function parseClass( ? SimpleType::fromNode($class->scalarType) : null, $isDeprecated, $isStrictProperties, + $attributes, $isNotSerializable, $extends, $implements, @@ -3317,7 +3571,8 @@ function parseClass( $properties, $methods, $enumCases, - $cond + $cond, + $minimumPhpVersionIdCompatibility ); } @@ -3389,6 +3644,7 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac 0, $stmt->getDocComment(), $cond, + $fileInfo->generateLegacyArginfoForPhpVersionId ); } continue; @@ -3429,7 +3685,8 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac $const, $classStmt->flags, $classStmt->getDocComment(), - $cond + $cond, + $fileInfo->generateLegacyArginfoForPhpVersionId ); } } else if ($classStmt instanceof Stmt\Property) { @@ -3443,7 +3700,8 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac $property, $classStmt->type, $classStmt->getDocComment(), - $prettyPrinter + $prettyPrinter, + $fileInfo->generateLegacyArginfoForPhpVersionId ); } } else if ($classStmt instanceof Stmt\ClassMethod) { @@ -3467,11 +3725,19 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac } $fileInfo->classInfos[] = parseClass( - $className, $stmt, $constInfos, $propertyInfos, $methodInfos, $enumCaseInfos, $cond + $className, $stmt, $constInfos, $propertyInfos, $methodInfos, $enumCaseInfos, $cond, $fileInfo->generateLegacyArginfoForPhpVersionId ); continue; } + if ($stmt instanceof Stmt\Expression) { + $expr = $stmt->expr; + if ($expr instanceof Expr\Include_) { + $fileInfo->dependencies[] = (string)EvaluatedValue::createFromExpression($expr->expr, null, null, [])->value; + continue; + } + } + throw new Exception("Unexpected node {$stmt->getType()}"); } } @@ -3499,7 +3765,14 @@ protected function pName_FullyQualified(Name\FullyQualified $node) { $fileInfo->generateFunctionEntries = true; $fileInfo->declarationPrefix = $tag->value ? $tag->value . " " : ""; } else if ($tag->name === 'generate-legacy-arginfo') { - $fileInfo->generateLegacyArginfo = true; + if ($tag->value && !in_array((int) $tag->value, ALL_PHP_VERSION_IDS, true)) { + throw new Exception( + "Legacy PHP version must be one of: \"" . PHP_70_VERSION_ID . "\" (PHP 7.0), \"" . PHP_80_VERSION_ID . "\" (PHP 8.0), " . + "\"" . PHP_81_VERSION_ID . "\" (PHP 8.1), \"" . PHP_82_VERSION_ID . "\" (PHP 8.2), \"" . $tag->value . "\" provided" + ); + } + + $fileInfo->generateLegacyArginfoForPhpVersionId = $tag->value ? (int) $tag->value : PHP_70_VERSION_ID; } else if ($tag->name === 'generate-class-entries') { $fileInfo->generateClassEntries = true; $fileInfo->declarationPrefix = $tag->value ? $tag->value . " " : ""; @@ -3516,12 +3789,16 @@ protected function pName_FullyQualified(Name\FullyQualified $node) { return $fileInfo; } -function funcInfoToCode(FuncInfo $funcInfo): string { +function funcInfoToCode(FileInfo $fileInfo, FuncInfo $funcInfo): string { $code = ''; $returnType = $funcInfo->return->type; $isTentativeReturnType = $funcInfo->return->tentativeReturnType; + $php81MinimumCompatibility = $fileInfo->generateLegacyArginfoForPhpVersionId === null || $fileInfo->generateLegacyArginfoForPhpVersionId >= PHP_81_VERSION_ID; if ($returnType !== null) { + if ($isTentativeReturnType && !$php81MinimumCompatibility) { + $code .= "#if (PHP_VERSION_ID >= " . PHP_81_VERSION_ID . ")\n"; + } if (null !== $simpleReturnType = $returnType->tryToSimpleType()) { if ($simpleReturnType->isBuiltin) { $code .= sprintf( @@ -3560,6 +3837,12 @@ function funcInfoToCode(FuncInfo $funcInfo): string { ); } } + if ($isTentativeReturnType && !$php81MinimumCompatibility) { + $code .= sprintf( + "#else\nZEND_BEGIN_ARG_INFO_EX(%s, 0, %d, %d)\n#endif\n", + $funcInfo->getArgInfoName(), $funcInfo->return->byRef, $funcInfo->numRequiredArgs + ); + } } else { $code .= sprintf( "ZEND_BEGIN_ARG_INFO_EX(%s, 0, %d, %d)\n", @@ -3672,7 +3955,7 @@ function generateArgInfoCode( $generatedFuncInfos = []; $code .= generateCodeWithConditions( $fileInfo->getAllFuncInfos(), "\n", - static function (FuncInfo $funcInfo) use (&$generatedFuncInfos) { + static function (FuncInfo $funcInfo) use (&$generatedFuncInfos, $fileInfo) { /* If there already is an equivalent arginfo structure, only emit a #define */ if ($generatedFuncInfo = findEquivalentFuncInfo($generatedFuncInfos, $funcInfo)) { $code = sprintf( @@ -3680,7 +3963,7 @@ static function (FuncInfo $funcInfo) use (&$generatedFuncInfos) { $funcInfo->getArgInfoName(), $generatedFuncInfo->getArgInfoName() ); } else { - $code = funcInfoToCode($funcInfo); + $code = funcInfoToCode($fileInfo, $funcInfo); } $generatedFuncInfos[] = $funcInfo; @@ -3715,7 +3998,7 @@ static function (FuncInfo $funcInfo) use ($fileInfo, &$generatedFunctionDeclarat } if ($fileInfo->generateClassEntries) { - $attributeInitializationCode = generateAttributeInitialization($fileInfo->funcInfos); + $attributeInitializationCode = generateAttributeInitialization($fileInfo->funcInfos, $allConstInfos, null); if ($attributeInitializationCode !== "" || !empty($fileInfo->constInfos)) { $code .= "\nstatic void register_{$stubFilenameWithoutExtension}_symbols(int module_number)\n"; @@ -3782,25 +4065,23 @@ function generateFunctionEntries(?Name $className, array $funcInfos, ?string $co /** * @param iterable $funcInfos */ -function generateAttributeInitialization(iterable $funcInfos, ?string $parentCond = null): string { +function generateAttributeInitialization(iterable $funcInfos, iterable $allConstInfos, ?string $parentCond = null): string { return generateCodeWithConditions( $funcInfos, "", - static function (FuncInfo $funcInfo) { + static function (FuncInfo $funcInfo) use ($allConstInfos) { $code = null; foreach ($funcInfo->args as $index => $arg) { - if (!$arg->isSensitive) { - continue; - } - if ($funcInfo->name instanceof MethodName) { $functionTable = "&class_entry->function_table"; } else { $functionTable = "CG(function_table)"; } - $code .= "\tzend_mark_function_parameter_as_sensitive($functionTable, \"" . $funcInfo->name->getNameForAttributes() . "\", $index);\n"; + foreach ($arg->attributes as $attribute) { + $code .= $attribute->generateCode("zend_add_parameter_attribute(zend_hash_str_find_ptr($functionTable, \"" . $funcInfo->name->getNameForAttributes() . "\", sizeof(\"" . $funcInfo->name->getNameForAttributes() . "\") - 1), $index", "{$funcInfo->name->getMethodSynopsisFilename()}_arg{$index}", $allConstInfos); + } } return $code; @@ -3825,6 +4106,87 @@ function generateOptimizerInfo(array $funcInfos): string { return $code; } +/** + * @param array $flagsByPhpVersions + * @return string[] + */ +function generateVersionDependentFlagCode(string $codeTemplate, array $flagsByPhpVersions, ?int $phpVersionIdMinimumCompatibility): array +{ + $phpVersions = ALL_PHP_VERSION_IDS; + sort($phpVersions); + $currentPhpVersion = end($phpVersions); + + // No version compatibility is needed + if ($phpVersionIdMinimumCompatibility === null) { + if (empty($flagsByPhpVersions[$currentPhpVersion])) { + return []; + } + + return [sprintf($codeTemplate, implode("|", $flagsByPhpVersions[$currentPhpVersion]))]; + } + + // Remove flags which depend on a PHP version below the minimally supported one + ksort($flagsByPhpVersions); + $index = array_search($phpVersionIdMinimumCompatibility, array_keys($flagsByPhpVersions)); + if ($index === false) { + throw new Exception("Missing version dependent flags for PHP version ID \"$phpVersionIdMinimumCompatibility\""); + } + $flagsByPhpVersions = array_slice($flagsByPhpVersions, $index, null, true); + + // Remove empty version-specific flags + $flagsByPhpVersions = array_filter( + $flagsByPhpVersions, + static function (array $value): bool { + return !empty($value); + }); + + // There are no version-specific flags + if (empty($flagsByPhpVersions)) { + return []; + } + + // Remove version-specific flags which don't differ from the previous one + $previousVersionId = null; + foreach ($flagsByPhpVersions as $versionId => $versionFlags) { + if ($previousVersionId !== null && $flagsByPhpVersions[$previousVersionId] === $versionFlags) { + unset($flagsByPhpVersions[$versionId]); + } else { + $previousVersionId = $versionId; + } + } + + $flagCount = count($flagsByPhpVersions); + + // Do not add a condition unnecessarily when the only version is the same as the minimally supported one + if ($flagCount === 1) { + reset($flagsByPhpVersions); + $firstVersion = key($flagsByPhpVersions); + if ($firstVersion === $phpVersionIdMinimumCompatibility) { + return [sprintf($codeTemplate, implode("|", reset($flagsByPhpVersions)))]; + } + } + + // Add the necessary conditions around the code using the version-specific flags + $result = []; + $i = 0; + foreach (array_reverse($flagsByPhpVersions, true) as $version => $versionFlags) { + $code = ""; + + $if = $i === 0 ? "#if" : "#elif"; + $endif = $i === $flagCount - 1 ? "#endif\n" : ""; + + $code .= "$if (PHP_VERSION_ID >= $version)\n"; + + $code .= sprintf($codeTemplate, implode("|", $versionFlags)); + $code .= $endif; + + $result[] = $code; + $i++; + } + + return $result; +} + /** * @param array $classMap * @param iterable $allConstInfos diff --git a/configure.ac b/configure.ac index 73c7edeae3db1..44f6da3f7d1d5 100644 --- a/configure.ac +++ b/configure.ac @@ -398,6 +398,7 @@ langinfo.h \ linux/filter.h \ linux/sock_diag.h \ malloc.h \ +os/signpost.h \ poll.h \ pty.h \ pwd.h \ @@ -597,6 +598,7 @@ mmap \ nice \ nl_langinfo \ poll \ +pthread_jit_write_protect_np \ putenv \ scandir \ setitimer \ @@ -689,7 +691,7 @@ if test "$ac_cv_func_getaddrinfo" = yes; then AC_DEFINE(HAVE_GETADDRINFO,1,[Define if you have the getaddrinfo function]) fi -AC_REPLACE_FUNCS(strlcat strlcpy explicit_bzero getopt) +AC_REPLACE_FUNCS(strlcat strlcpy explicit_bzero getopt reallocarray) AC_FUNC_ALLOCA PHP_TIME_R_TYPE PHP_CHECK_IN_ADDR_T @@ -1616,7 +1618,7 @@ PHP_ADD_SOURCES(main, main.c snprintf.c spprintf.c \ php_ini_builder.c \ php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \ strlcat.c explicit_bzero.c reentrancy.c php_variables.c php_ticks.c \ - network.c php_open_temporary_file.c php_odbc_utils.c \ + network.c php_open_temporary_file.c php_odbc_utils.c safe_bcmp.c reallocarray.c \ output.c getopt.c php_syslog.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) PHP_ADD_SOURCES_X(main, fastcgi.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1, PHP_FASTCGI_OBJS, no) diff --git a/docs/release-process.md b/docs/release-process.md index d55e881e9daa2..c17b83707cc4c 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -121,15 +121,15 @@ slightly different steps. We'll call attention where the steps differ. 3. Check out the *release branch* for this release from the *version branch*. > 🔶 **Non-stable version branches: pre-GA** \ - > There is no *version branch* for alpha releases. Instead, treat the main - > branch as the version branch. You will create a local-only release branch - > from the main branch. Do not push it! + > There is no *version branch* for alpha or beta releases. Instead, treat the + > main branch as the version branch. You will create a local-only release + > branch from the main branch. Do not push it! > > ```shell > git checkout -b php-X.Y.0alpha1-local-release-branch upstream/master > ``` > - > During the first beta release, you will create (and push!) the version + > During the first RC release, you will create (and push!) the version > branch for the pre-GA release, e.g., `PHP-8.2`. See > "[Forking a new version branch](#forking-a-new-version-branch)" below. > From this point forward, all pre-GA release branches will be created from @@ -296,7 +296,7 @@ slightly different steps. We'll call attention where the steps differ. upload to GitHub and include in the announcement emails. ```shell - ./scripts/dev/gen_verify_stub php-X.Y.ZRCn YOURKEYID > php-X.Y.ZRCn.manifest + ./scripts/dev/gen_verify_stub X.Y.ZRCn YOURKEYID > php-X.Y.ZRCn.manifest ``` 13. If you have the [GitHub command line tool][] installed, run the following to @@ -569,7 +569,7 @@ slightly different steps. We'll call attention where the steps differ. upload to GitHub and include in the announcement emails. ```shell - ./scripts/dev/gen_verify_stub php-X.Y.Z YOURKEYID > php-X.Y.Z.manifest + ./scripts/dev/gen_verify_stub X.Y.Z YOURKEYID > php-X.Y.Z.manifest ``` 12. If you have the [GitHub command line tool][] installed, run the following to @@ -845,16 +845,15 @@ recommendation and the intervals may vary based on work load. ## Forking a new version branch -When the new version has reached the feature freeze point during its pre-release -cycle, it is time to create a new version branch. This frees up the main branch -(i.e., `master`) for any new feature development that cannot go into the new -version. +When the new version has reached the first RC, it is time to create a new +version branch. This frees up the main branch (i.e., `master`) for any new +feature development that cannot go into the new version. -1. One week prior to tagging `X.Y.0beta1`, warn internals@ that your version's +1. One week prior to tagging `X.Y.0RC1`, warn internals@ that your version's branch is about to be created. Be specific about when the branch creation will occur. For example: https://news-web.php.net/php.internals/99864 -2. Just prior to tagging `X.Y.0beta1`, create the new version branch locally, +2. Just prior to tagging `X.Y.0RC1`, create the new version branch locally, i.e. `PHP-X.Y`. 3. Add a commit on the main branch (i.e., `master`) after the branch point. @@ -885,6 +884,13 @@ version. * [Add PHP-8.1 to the Git steps page][] * [Changes to the wiki][] +> 💬 **Hint** \ +> We create the new version branch at the first release candidate rather than at +> feature freeze to allow a period of time where the focus is on making the new +> version ready for RC and GA. During this time, the main branch is *only* for +> minor improvements and bug fixes. All major improvements and new features must +> wait. + ## Preparing for the initial stable version (PHP X.Y.0) diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index 1b50764b828aa..d6147269b0ebb 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -62,7 +62,7 @@ ZEND_INI_MH(OnUpdateScale) int *p; zend_long tmp; - tmp = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + tmp = zend_ini_parse_quantity_warn(new_value, entry->name); if (tmp < 0 || tmp > INT_MAX) { return FAILURE; } diff --git a/ext/bz2/bz2_filter.c b/ext/bz2/bz2_filter.c index 4c573638366f1..9b3480b4a5ca9 100644 --- a/ext/bz2/bz2_filter.c +++ b/ext/bz2/bz2_filter.c @@ -366,7 +366,7 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi /* How much memory to allocate (1 - 9) x 100kb */ zend_long blocks = zval_get_long(tmpzval); if (blocks < 1 || blocks > 9) { - php_error_docref(NULL, E_WARNING, "Invalid parameter given for number of blocks to allocate. (" ZEND_LONG_FMT ")", blocks); + php_error_docref(NULL, E_WARNING, "Invalid parameter given for number of blocks to allocate (" ZEND_LONG_FMT ")", blocks); } else { blockSize100k = (int) blocks; } @@ -376,7 +376,7 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi /* Work Factor (0 - 250) */ zend_long work = zval_get_long(tmpzval); if (work < 0 || work > 250) { - php_error_docref(NULL, E_WARNING, "Invalid parameter given for work factor. (" ZEND_LONG_FMT ")", work); + php_error_docref(NULL, E_WARNING, "Invalid parameter given for work factor (" ZEND_LONG_FMT ")", work); } else { workFactor = (int) work; } diff --git a/ext/bz2/tests/bug72447.phpt b/ext/bz2/tests/bug72447.phpt index 7cbd43a443802..11f3bd9136b54 100644 --- a/ext/bz2/tests/bug72447.phpt +++ b/ext/bz2/tests/bug72447.phpt @@ -16,4 +16,4 @@ fclose($fp); unlink('testfile'); ?> --EXPECTF-- -Warning: stream_filter_append(): Invalid parameter given for number of blocks to allocate. (0) in %s%ebug72447.php on line %d +Warning: stream_filter_append(): Invalid parameter given for number of blocks to allocate (0) in %s%ebug72447.php on line %d diff --git a/ext/calendar/calendar.stub.php b/ext/calendar/calendar.stub.php index a20079ae3da9e..5418781332f65 100644 --- a/ext/calendar/calendar.stub.php +++ b/ext/calendar/calendar.stub.php @@ -4,111 +4,111 @@ /** * @var int - * @cname CAL_GREGORIAN + * @cvalue CAL_GREGORIAN */ const CAL_GREGORIAN = UNKNOWN; /** * @var int - * @cname CAL_JULIAN + * @cvalue CAL_JULIAN */ const CAL_JULIAN = UNKNOWN; /** * @var int - * @cname CAL_JEWISH + * @cvalue CAL_JEWISH */ const CAL_JEWISH = UNKNOWN; /** * @var int - * @cname CAL_FRENCH + * @cvalue CAL_FRENCH */ const CAL_FRENCH = UNKNOWN; /** * @var int - * @cname CAL_NUM_CALS + * @cvalue CAL_NUM_CALS */ const CAL_NUM_CALS = UNKNOWN; /** * @var int - * @cname CAL_DOW_DAYNO + * @cvalue CAL_DOW_DAYNO */ const CAL_DOW_DAYNO = UNKNOWN; /** * @var int - * @cname CAL_DOW_SHORT + * @cvalue CAL_DOW_SHORT */ const CAL_DOW_SHORT = UNKNOWN; /** * @var int - * @cname CAL_DOW_LONG + * @cvalue CAL_DOW_LONG */ const CAL_DOW_LONG = UNKNOWN; /** * @var int - * @cname CAL_MONTH_GREGORIAN_SHORT + * @cvalue CAL_MONTH_GREGORIAN_SHORT */ const CAL_MONTH_GREGORIAN_SHORT = UNKNOWN; /** * @var int - * @cname CAL_MONTH_GREGORIAN_LONG + * @cvalue CAL_MONTH_GREGORIAN_LONG */ const CAL_MONTH_GREGORIAN_LONG = UNKNOWN; /** * @var int - * @cname CAL_MONTH_JULIAN_SHORT + * @cvalue CAL_MONTH_JULIAN_SHORT */ const CAL_MONTH_JULIAN_SHORT = UNKNOWN; /** * @var int - * @cname CAL_MONTH_JULIAN_LONG + * @cvalue CAL_MONTH_JULIAN_LONG */ const CAL_MONTH_JULIAN_LONG = UNKNOWN; /** * @var int - * @cname CAL_MONTH_JEWISH + * @cvalue CAL_MONTH_JEWISH */ const CAL_MONTH_JEWISH = UNKNOWN; /** * @var int - * @cname CAL_MONTH_FRENCH + * @cvalue CAL_MONTH_FRENCH */ const CAL_MONTH_FRENCH = UNKNOWN; /** * @var int - * @cname CAL_EASTER_DEFAULT + * @cvalue CAL_EASTER_DEFAULT */ const CAL_EASTER_DEFAULT = UNKNOWN; /** * @var int - * @cname CAL_EASTER_ROMAN + * @cvalue CAL_EASTER_ROMAN */ const CAL_EASTER_ROMAN = UNKNOWN; /** * @var int - * @cname CAL_EASTER_ALWAYS_GREGORIAN + * @cvalue CAL_EASTER_ALWAYS_GREGORIAN */ const CAL_EASTER_ALWAYS_GREGORIAN = UNKNOWN; /** * @var int - * @cname CAL_EASTER_ALWAYS_JULIAN + * @cvalue CAL_EASTER_ALWAYS_JULIAN */ const CAL_EASTER_ALWAYS_JULIAN = UNKNOWN; /** * @var int - * @cname CAL_JEWISH_ADD_ALAFIM_GERESH + * @cvalue CAL_JEWISH_ADD_ALAFIM_GERESH */ const CAL_JEWISH_ADD_ALAFIM_GERESH = UNKNOWN; /** * @var int - * @cname CAL_JEWISH_ADD_ALAFIM + * @cvalue CAL_JEWISH_ADD_ALAFIM */ const CAL_JEWISH_ADD_ALAFIM = UNKNOWN; /** * @var int - * @cname CAL_JEWISH_ADD_GERESHAYIM + * @cvalue CAL_JEWISH_ADD_GERESHAYIM */ const CAL_JEWISH_ADD_GERESHAYIM = UNKNOWN; diff --git a/ext/calendar/calendar_arginfo.h b/ext/calendar/calendar_arginfo.h index 3b6b2af152a97..f518d36e413bb 100644 --- a/ext/calendar/calendar_arginfo.h +++ b/ext/calendar/calendar_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 6030cc249e7c1950818b3060ed2e565119710546 */ + * Stub hash: f45116785b01842f56ff923a54f65ab839b3dd61 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_cal_days_in_month, 0, 3, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, calendar, IS_LONG, 0) diff --git a/ext/com_dotnet/com_extension.c b/ext/com_dotnet/com_extension.c index 5782102201f61..95361a4b9a9ed 100644 --- a/ext/com_dotnet/com_extension.c +++ b/ext/com_dotnet/com_extension.c @@ -32,11 +32,13 @@ #define PHP_DISP_E_DIVBYZERO ((zend_long) (ULONG) DISP_E_DIVBYZERO) #define PHP_DISP_E_OVERFLOW ((zend_long) (ULONG) DISP_E_OVERFLOW) #define PHP_DISP_E_BADINDEX ((zend_long) (ULONG) DISP_E_BADINDEX) +#define PHP_DISP_E_PARAMNOTFOUND ((zend_long) (ULONG) DISP_E_PARAMNOTFOUND) #define PHP_MK_E_UNAVAILABLE ((zend_long) (ULONG) MK_E_UNAVAILABLE) #else #define PHP_DISP_E_DIVBYZERO DISP_E_DIVBYZERO #define PHP_DISP_E_OVERFLOW DISP_E_OVERFLOW #define PHP_DISP_E_BADINDEX DISP_E_BADINDEX +#define PHP_DISP_E_PARAMNOTFOUND DISP_E_PARAMNOTFOUND #define PHP_MK_E_UNAVAILABLE MK_E_UNAVAILABLE #endif diff --git a/ext/com_dotnet/com_extension.stub.php b/ext/com_dotnet/com_extension.stub.php index 54f31992ef7a4..3207871f85c7d 100644 --- a/ext/com_dotnet/com_extension.stub.php +++ b/ext/com_dotnet/com_extension.stub.php @@ -4,281 +4,286 @@ /** * @var int - * @cname CLSCTX_INPROC_SERVER + * @cvalue CLSCTX_INPROC_SERVER */ const CLSCTX_INPROC_SERVER = UNKNOWN; /** * @var int - * @cname CLSCTX_INPROC_HANDLER + * @cvalue CLSCTX_INPROC_HANDLER */ const CLSCTX_INPROC_HANDLER = UNKNOWN; /** * @var int - * @cname CLSCTX_LOCAL_SERVER + * @cvalue CLSCTX_LOCAL_SERVER */ const CLSCTX_LOCAL_SERVER = UNKNOWN; /** * @var int - * @cname CLSCTX_REMOTE_SERVER + * @cvalue CLSCTX_REMOTE_SERVER */ const CLSCTX_REMOTE_SERVER = UNKNOWN; /** * @var int - * @cname CLSCTX_SERVER + * @cvalue CLSCTX_SERVER */ const CLSCTX_SERVER = UNKNOWN; /** * @var int - * @cname CLSCTX_ALL + * @cvalue CLSCTX_ALL */ const CLSCTX_ALL = UNKNOWN; /** * @var int - * @cname VT_NULL + * @cvalue VT_NULL */ const VT_NULL = UNKNOWN; /** * @var int - * @cname VT_EMPTY + * @cvalue VT_EMPTY */ const VT_EMPTY = UNKNOWN; /** * @var int - * @cname VT_UI1 + * @cvalue VT_UI1 */ const VT_UI1 = UNKNOWN; /** * @var int - * @cname VT_I1 + * @cvalue VT_I1 */ const VT_I1 = UNKNOWN; /** * @var int - * @cname VT_UI2 + * @cvalue VT_UI2 */ const VT_UI2 = UNKNOWN; /** * @var int - * @cname VT_I2 + * @cvalue VT_I2 */ const VT_I2 = UNKNOWN; /** * @var int - * @cname VT_UI4 + * @cvalue VT_UI4 */ const VT_UI4 = UNKNOWN; /** * @var int - * @cname VT_I4 + * @cvalue VT_I4 */ const VT_I4 = UNKNOWN; /** * @var int - * @cname VT_R4 + * @cvalue VT_R4 */ const VT_R4 = UNKNOWN; /** * @var int - * @cname VT_R8 + * @cvalue VT_R8 */ const VT_R8 = UNKNOWN; /** * @var int - * @cname VT_BOOL + * @cvalue VT_BOOL */ const VT_BOOL = UNKNOWN; /** * @var int - * @cname VT_ERROR + * @cvalue VT_ERROR */ const VT_ERROR = UNKNOWN; /** * @var int - * @cname VT_CY + * @cvalue VT_CY */ const VT_CY = UNKNOWN; /** * @var int - * @cname VT_DATE + * @cvalue VT_DATE */ const VT_DATE = UNKNOWN; /** * @var int - * @cname VT_BSTR + * @cvalue VT_BSTR */ const VT_BSTR = UNKNOWN; /** * @var int - * @cname VT_DECIMAL + * @cvalue VT_DECIMAL */ const VT_DECIMAL = UNKNOWN; /** * @var int - * @cname VT_UNKNOWN + * @cvalue VT_UNKNOWN */ const VT_UNKNOWN = UNKNOWN; /** * @var int - * @cname VT_DISPATCH + * @cvalue VT_DISPATCH */ const VT_DISPATCH = UNKNOWN; /** * @var int - * @cname VT_VARIANT + * @cvalue VT_VARIANT */ const VT_VARIANT = UNKNOWN; /** * @var int - * @cname VT_INT + * @cvalue VT_INT */ const VT_INT = UNKNOWN; /** * @var int - * @cname VT_UINT + * @cvalue VT_UINT */ const VT_UINT = UNKNOWN; /** * @var int - * @cname VT_ARRAY + * @cvalue VT_ARRAY */ const VT_ARRAY = UNKNOWN; /** * @var int - * @cname VT_BYREF + * @cvalue VT_BYREF */ const VT_BYREF = UNKNOWN; /** * @var int - * @cname CP_ACP + * @cvalue CP_ACP */ const CP_ACP = UNKNOWN; /** * @var int - * @cname CP_MACCP + * @cvalue CP_MACCP */ const CP_MACCP = UNKNOWN; /** * @var int - * @cname CP_OEMCP + * @cvalue CP_OEMCP */ const CP_OEMCP = UNKNOWN; /** * @var int - * @cname CP_UTF7 + * @cvalue CP_UTF7 */ const CP_UTF7 = UNKNOWN; /** * @var int - * @cname CP_UTF8 + * @cvalue CP_UTF8 */ const CP_UTF8 = UNKNOWN; /** * @var int - * @cname CP_SYMBOL + * @cvalue CP_SYMBOL */ const CP_SYMBOL = UNKNOWN; /** * @var int - * @cname CP_THREAD_ACP + * @cvalue CP_THREAD_ACP */ const CP_THREAD_ACP = UNKNOWN; /** * @var int - * @cname VARCMP_LT + * @cvalue VARCMP_LT */ const VARCMP_LT = UNKNOWN; /** * @var int - * @cname VARCMP_EQ + * @cvalue VARCMP_EQ */ const VARCMP_EQ = UNKNOWN; /** * @var int - * @cname VARCMP_GT + * @cvalue VARCMP_GT */ const VARCMP_GT = UNKNOWN; /** * @var int - * @cname VARCMP_NULL + * @cvalue VARCMP_NULL */ const VARCMP_NULL = UNKNOWN; /** * @var int - * @cname LOCALE_SYSTEM_DEFAULT + * @cvalue LOCALE_SYSTEM_DEFAULT */ const LOCALE_SYSTEM_DEFAULT = UNKNOWN; /** * @var int - * @cname LOCALE_NEUTRAL + * @cvalue LOCALE_NEUTRAL */ const LOCALE_NEUTRAL = UNKNOWN; /** * @var int - * @cname NORM_IGNORECASE + * @cvalue NORM_IGNORECASE */ const NORM_IGNORECASE = UNKNOWN; /** * @var int - * @cname NORM_IGNORENONSPACE + * @cvalue NORM_IGNORENONSPACE */ const NORM_IGNORENONSPACE = UNKNOWN; /** * @var int - * @cname NORM_IGNORESYMBOLS + * @cvalue NORM_IGNORESYMBOLS */ const NORM_IGNORESYMBOLS = UNKNOWN; /** * @var int - * @cname NORM_IGNOREWIDTH + * @cvalue NORM_IGNOREWIDTH */ const NORM_IGNOREWIDTH = UNKNOWN; /** * @var int - * @cname NORM_IGNOREKANATYPE + * @cvalue NORM_IGNOREKANATYPE */ const NORM_IGNOREKANATYPE = UNKNOWN; #ifdef NORM_IGNOREKASHIDA /** * @var int - * @cname NORM_IGNOREKASHIDA + * @cvalue NORM_IGNOREKASHIDA */ const NORM_IGNOREKASHIDA = UNKNOWN; #endif /** * @var int - * @cname PHP_DISP_E_DIVBYZERO + * @cvalue PHP_DISP_E_DIVBYZERO */ const DISP_E_DIVBYZERO = UNKNOWN; /** * @var int - * @cname PHP_DISP_E_OVERFLOW + * @cvalue PHP_DISP_E_OVERFLOW */ const DISP_E_OVERFLOW = UNKNOWN; /** * @var int - * @cname PHP_DISP_E_BADINDEX + * @cvalue PHP_DISP_E_BADINDEX */ const DISP_E_BADINDEX = UNKNOWN; /** * @var int - * @cname PHP_MK_E_UNAVAILABLE + * @cvalue PHP_DISP_E_PARAMNOTFOUND + */ +const DISP_E_PARAMNOTFOUND = UNKNOWN; +/** + * @var int + * @cvalue PHP_MK_E_UNAVAILABLE */ const MK_E_UNAVAILABLE = UNKNOWN; #if SIZEOF_ZEND_LONG == 8 /** * @var int - * @cname VT_UI8 + * @cvalue VT_UI8 */ const VT_UI8 = UNKNOWN; /** * @var int - * @cname VT_I8 + * @cvalue VT_I8 */ const VT_I8 = UNKNOWN; #endif diff --git a/ext/com_dotnet/com_extension_arginfo.h b/ext/com_dotnet/com_extension_arginfo.h index fcca1ecbeefc1..7fda790b8a1ac 100644 --- a/ext/com_dotnet/com_extension_arginfo.h +++ b/ext/com_dotnet/com_extension_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 76bd9190ad3f5e8fc3f6d6e0b5561f935c73efd3 */ + * Stub hash: b91206482b5119ce6d7c899e9599acfa2e06ec2a */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_variant_set, 0, 2, IS_VOID, 0) ZEND_ARG_OBJ_INFO(0, variant, variant, 0) @@ -292,6 +292,7 @@ static void register_com_extension_symbols(int module_number) REGISTER_LONG_CONSTANT("DISP_E_DIVBYZERO", PHP_DISP_E_DIVBYZERO, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("DISP_E_OVERFLOW", PHP_DISP_E_OVERFLOW, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("DISP_E_BADINDEX", PHP_DISP_E_BADINDEX, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("DISP_E_PARAMNOTFOUND", PHP_DISP_E_PARAMNOTFOUND, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MK_E_UNAVAILABLE", PHP_MK_E_UNAVAILABLE, CONST_CS | CONST_PERSISTENT); #if SIZEOF_ZEND_LONG == 8 REGISTER_LONG_CONSTANT("VT_UI8", VT_UI8, CONST_CS | CONST_PERSISTENT); diff --git a/ext/com_dotnet/com_handlers.c b/ext/com_dotnet/com_handlers.c index fe1b6f257b283..db96118ea31c6 100644 --- a/ext/com_dotnet/com_handlers.c +++ b/ext/com_dotnet/com_handlers.c @@ -429,7 +429,7 @@ static int com_objects_compare(zval *object1, zval *object2) return ret; } -static int com_object_cast(zend_object *readobj, zval *writeobj, int type) +static zend_result com_object_cast(zend_object *readobj, zval *writeobj, int type) { php_com_dotnet_object *obj; VARIANT v; @@ -452,7 +452,11 @@ static int com_object_cast(zend_object *readobj, zval *writeobj, int type) switch(type) { case IS_LONG: case _IS_NUMBER: - vt = VT_INT; +#if SIZEOF_ZEND_LONG == 4 + vt = VT_I4; +#else + vt = VT_I8; +#endif break; case IS_DOUBLE: vt = VT_R8; @@ -486,7 +490,7 @@ static int com_object_cast(zend_object *readobj, zval *writeobj, int type) return zend_std_cast_object_tostring(readobj, writeobj, type); } -static int com_object_count(zend_object *object, zend_long *count) +static zend_result com_object_count(zend_object *object, zend_long *count) { php_com_dotnet_object *obj; LONG ubound = 0, lbound = 0; diff --git a/ext/com_dotnet/com_saproxy.c b/ext/com_dotnet/com_saproxy.c index 4e19f6e78e5d2..6ad4680c0fe65 100644 --- a/ext/com_dotnet/com_saproxy.c +++ b/ext/com_dotnet/com_saproxy.c @@ -332,12 +332,12 @@ static int saproxy_objects_compare(zval *object1, zval *object2) return -1; } -static int saproxy_object_cast(zend_object *readobj, zval *writeobj, int type) +static zend_result saproxy_object_cast(zend_object *readobj, zval *writeobj, int type) { return FAILURE; } -static int saproxy_count_elements(zend_object *object, zend_long *count) +static zend_result saproxy_count_elements(zend_object *object, zend_long *count) { php_com_saproxy *proxy = (php_com_saproxy*) object; LONG ubound, lbound; diff --git a/ext/com_dotnet/com_variant.c b/ext/com_dotnet/com_variant.c index 40106e3d8f4ff..b40ac6a5c31f9 100644 --- a/ext/com_dotnet/com_variant.c +++ b/ext/com_dotnet/com_variant.c @@ -92,7 +92,7 @@ static void safe_array_from_zval(VARIANT *v, zval *z, int codepage) } } -PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage) +static void php_com_variant_from_zval_ex(VARIANT *v, zval *z, int codepage, VARTYPE vt) { php_com_dotnet_object *obj; zend_uchar ztype = IS_NULL; @@ -145,6 +145,11 @@ PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codep break; case IS_LONG: + if (vt == VT_ERROR) { + V_VT(v) = VT_ERROR; + V_ERROR(v) = Z_LVAL_P(z); + break; + } #if SIZEOF_ZEND_LONG == 4 V_VT(v) = VT_I4; V_I4(v) = Z_LVAL_P(z); @@ -172,6 +177,11 @@ PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codep } } +PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage) +{ + php_com_variant_from_zval_ex(v, z, codepage, VT_EMPTY); +} + PHP_COM_DOTNET_API zend_result php_com_zval_from_variant(zval *z, VARIANT *v, int codepage) { OLECHAR *olestring = NULL; @@ -448,7 +458,7 @@ PHP_METHOD(variant, __construct) } if (zvalue) { - php_com_variant_from_zval(&obj->v, zvalue, obj->code_page); + php_com_variant_from_zval_ex(&obj->v, zvalue, obj->code_page, vt); } /* Only perform conversion if variant not already of type passed */ @@ -1019,6 +1029,7 @@ PHP_FUNCTION(variant_set_type) zval *zobj; php_com_dotnet_object *obj; /* VARTYPE == unsigned short */ zend_long vt; + VARIANT vtmp; HRESULT res; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), @@ -1027,7 +1038,12 @@ PHP_FUNCTION(variant_set_type) } obj = CDNO_FETCH(zobj); - res = VariantChangeType(&obj->v, &obj->v, 0, (VARTYPE)vt); + if (V_VT(&obj->v) == VT_ERROR) { + VariantInit(&vtmp); + V_VT(&vtmp) = VT_I4; + V_I4(&vtmp) = V_ERROR(&obj->v); + } + res = VariantChangeType(&obj->v, V_VT(&obj->v) != VT_ERROR ? &obj->v : &vtmp, 0, (VARTYPE)vt); if (SUCCEEDED(res)) { if (vt != VT_DISPATCH && obj->typeinfo) { @@ -1063,7 +1079,11 @@ PHP_FUNCTION(variant_cast) obj = CDNO_FETCH(zobj); VariantInit(&vres); - res = VariantChangeType(&vres, &obj->v, 0, (VARTYPE)vt); + if (V_VT(&obj->v) == VT_ERROR) { + V_VT(&vres) = VT_I4; + V_I4(&vres) = V_ERROR(&obj->v); + } + res = VariantChangeType(&vres, V_VT(&vres) == VT_EMPTY ? &obj->v : &vres, 0, (VARTYPE)vt); if (SUCCEEDED(res)) { php_com_wrap_variant(return_value, &vres, obj->code_page); diff --git a/ext/com_dotnet/tests/bug77578.phpt b/ext/com_dotnet/tests/bug77578.phpt index abb68cc163f4f..653a16123218d 100644 --- a/ext/com_dotnet/tests/bug77578.phpt +++ b/ext/com_dotnet/tests/bug77578.phpt @@ -7,9 +7,13 @@ com_dotnet // To actually be able to verify the crash during shutdown on Windows, we have // to execute a PHP subprocess, and check its exit status. $php = PHP_BINARY; -$ini = php_ini_loaded_file(); -$iniopt = $ini ? "-c $ini" : ''; -$command = "$php $iniopt -d extension=com_dotnet -d com.autoregister_typelib=1 -r \"new COM('WbemScripting.SWbemLocator');\""; +$extension_dir = ini_get("extension_dir"); +$script = <<